summaryrefslogtreecommitdiff
path: root/py/emitbc.c
AgeCommit message (Collapse)Author
2021-02-04all: Rename BYTES_PER_WORD to MP_BYTES_PER_OBJ_WORD.Damien George
The "word" referred to by BYTES_PER_WORD is actually the size of mp_obj_t which is not always the same as the size of a pointer on the target architecture. So rename this config value to better reflect what it measures, and also prefix it with MP_. For uses of BYTES_PER_WORD in setting the stack limit this has been changed to sizeof(void *), because the stack usually grows with machine-word sized values (eg an nlr_buf_t has many machine words in it). Signed-off-by: Damien George <damien@micropython.org>
2020-04-23all: Format code to add space after C++-style comment start.stijn
Note: the uncrustify configuration is explicitly set to 'add' instead of 'force' in order not to alter the comments which use extra spaces after // as a means of indenting text for clarity.
2020-02-28all: Reformat C and Python source code with tools/codeformat.py.Damien George
This is run with uncrustify 0.70.1, and black 19.10b0.
2019-12-20py: Remove commented-out debug printf's from emitbc and objlist.Damien George
Any debugging prints should use a macro like DEBUG_printf.
2019-10-01py: Rework and compress second part of bytecode prelude.Damien George
This patch compresses the second part of the bytecode prelude which contains the source file name, function name, source-line-number mapping and cell closure information. This part of the prelude now begins with a single varible length unsigned integer which encodes 2 numbers, being the byte-size of the following 2 sections in the header: the "source info section" and the "closure section". After decoding this variable unsigned integer it's possible to skip over one or both of these sections very easily. This scheme saves about 2 bytes for most functions compared to the original format: one in the case that there are no closure cells, and one because padding was eliminated.
2019-10-01py: Compress first part of bytecode prelude.Damien George
The start of the bytecode prelude contains 6 numbers telling the amount of stack needed for the Python values and exceptions, and the signature of the function. Prior to this patch these numbers were all encoded one after the other (2x variable unsigned integers, then 4x bytes), but using so many bytes is unnecessary. An entropy analysis of around 150,000 bytecode functions from the CPython standard library showed that the optimal Shannon coding would need about 7.1 bits on average to encode these 6 numbers, compared to the existing 48 bits. This patch attempts to get close to this optimal value by packing the 6 numbers into a single, varible-length unsigned integer via bit-wise interleaving. The interleaving scheme is chosen to minimise the average number of bytes needed, and at the same time keep the scheme simple enough so it can be implemented without too much overhead in code size or speed. The scheme requires about 10.5 bits on average to store the 6 numbers. As a result most functions which originally took 6 bytes to encode these 6 numbers now need only 1 byte (in 80% of cases).
2019-09-26py: Split RAISE_VARARGS opcode into 3 separate ones.Damien George
From the beginning of this project the RAISE_VARARGS opcode was named and implemented following CPython, where it has an argument (to the opcode) counting how many args the raise takes: raise # 0 args (re-raise previous exception) raise exc # 1 arg raise exc from exc2 # 2 args (chained raise) In the bytecode this operation therefore takes 2 bytes, one for RAISE_VARARGS and one for the number of args. This patch splits this opcode into 3, where each is now a single byte. This reduces bytecode size by 1 byte for each use of raise. Every byte counts! It also has the benefit of reducing code size (on all ports except nanbox).
2019-09-26py: Introduce and use constants for multi-opcode sizes.Damien George
2019-08-30py: Integrate sys.settrace feature into the VM and runtime.Milan Rossa
This commit adds support for sys.settrace, allowing to install Python handlers to trace execution of Python code. The interface follows CPython as closely as possible. The feature is disabled by default and can be enabled via MICROPY_PY_SYS_SETTRACE.
2019-08-22py/emitbc: Make all emit_write_bytecode_* funcs take a stack_adj arg.Damien George
This factoring of code gives significant code-size savings: bare-arm: -456 -0.682% minimal x86: -844 -0.547% unix x64: -472 -0.095% unix nanbox: -1348 -0.303% stm32: -472 -0.130% PYBV10 cc3200: -448 -0.242% esp8266: -708 -0.108% esp32: -400 -0.036% GENERIC nrf: -520 -0.356% pca10040 samd: -456 -0.448% ADAFRUIT_ITSYBITSY_M4_EXPRESS
2019-08-22py/emitbc: Rewrite switch in load_const_tok to reduce code size.Damien George
2019-03-14py/compile: Add support to select the native emitter at runtime.Damien George
2019-03-05py: Replace POP_BLOCK and POP_EXCEPT opcodes with POP_EXCEPT_JUMP.Damien George
POP_BLOCK and POP_EXCEPT are now the same, and are always followed by a JUMP. So this optimisation reduces code size, and RAM usage of bytecode by two bytes for each try-except handler.
2019-03-05py: Fix VM crash with unwinding jump out of a finally block.Damien George
This patch fixes a bug in the VM when breaking within a try-finally. The bug has to do with executing a break within the finally block of a try-finally statement. For example: def f(): for x in (1,): print('a', x) try: raise Exception finally: print(1) break print('b', x) f() Currently in uPy the above code will print: a 1 1 1 segmentation fault (core dumped) micropython Not only is there a seg fault, but the "1" in the finally block is printed twice. This is because when the VM executes a finally block it doesn't really know if that block was executed due to a fall-through of the try (no exception raised), or because an exception is active. In particular, for nested finallys the VM has no idea which of the nested ones have active exceptions and which are just fall-throughs. So when a break (or continue) is executed it tries to unwind all of the finallys, when in fact only some may be active. It's questionable whether break (or return or continue) should be allowed within a finally block, because they implicitly swallow any active exception, but nevertheless it's allowed by CPython (although almost never used in the standard library). And uPy should at least not crash in such a case. The solution here relies on the fact that exception and finally handlers always appear in the bytecode after the try body. Note: there was a similar bug with a return in a finally block, but that was previously fixed in b735208403a54774f9fd3d966f7c1a194c41870f
2019-01-04py: Get optional VM stack overflow check compiling and working again.Damien George
Changes to the layout of the bytecode header meant that this debug code was no longer compiling. This is now fixed and a new compile-time option is introduced, MICROPY_DEBUG_VM_STACK_OVERFLOW, to turn on this feature (which is disabled by default). This option is needed because more than one file needs to cooperate to make this check work.
2018-09-15py/emit: Completely remove set_native_type, arg type is set in compiler.Damien George
In viper mode, the type of the argument is now stored in id_info->flags.
2018-05-23py/emit: Combine setup with/except/finally into one emit function.Damien George
This patch reduces code size by: bare-arm: -16 minimal x86: -156 unix x64: -288 unix nanbox: -184 stm32: -48 cc3200: -16 esp8266: -96 esp32: -16 The last 10 patches combined reduce code size by: bare-arm: -164 minimal x86: -1260 unix x64: -3416 unix nanbox: -1616 stm32: -676 cc3200: -232 esp8266: -1144 esp32: -268
2018-05-23py/emit: Merge build set/slice into existing build emit function.Damien George
Reduces code size by: bare-arm: +0 minimal x86: +0 unix x64: -368 unix nanbox: -248 stm32: -128 cc3200: -48 esp8266: -184 esp32: -40
2018-05-23py/emit: Combine import from/name/star into one emit function.Damien George
Change in code size is: bare-arm: +4 minimal x86: -88 unix x64: -456 unix nanbox: -88 stm32: -44 cc3200: +0 esp8266: -104 esp32: +8
2018-05-23py/emit: Combine break_loop and continue_loop into one emit function.Damien George
Reduces code size by: bare-arm: +0 minimal x86: +0 unix x64: -80 unix nanbox: +0 stm32: -12 cc3200: +0 esp8266: -28 esp32: +0
2018-05-23py/emit: Combine load/store/delete attr into one emit function.Damien George
Reduces code size by: bare-arm: -20 minimal x86: -140 unix x64: -408 unix nanbox: -140 stm32: -68 cc3200: -16 esp8266: -80 esp32: -32
2018-05-23py/emit: Combine load/store/delete subscr into one emit function.Damien George
Reduces code size by: bare-arm: -8 minimal x86: -104 unix x64: -312 unix nanbox: -120 stm32: -60 cc3200: -16 esp8266: -92 esp32: -24
2018-05-23py/emit: Combine name and global into one func for load/store/delete.Damien George
Reduces code size by: bare-arm: -56 minimal x86: -300 unix x64: -576 unix nanbox: -300 stm32: -164 cc3200: -56 esp8266: -236 esp32: -76
2018-05-23py/emit: Combine build tuple/list/map emit funcs into one.Damien George
Reduces code size by: bare-arm: -24 minimal x86: -192 unix x64: -288 unix nanbox: -184 stm32: -72 cc3200: -16 esp8266: -148 esp32: -32
2018-05-23py/emit: Combine yield value and yield-from emit funcs into one.Damien George
Reduces code size by: bare-arm: -24 minimal x86: -72 unix x64: -200 unix nanbox: -72 stm32: -52 cc3200: -32 esp8266: -84 esp32: -24
2018-05-23py/emit: Combine fast and deref into one function for load/store/delete.Damien George
Reduces code size by: bare-arm: -16 minimal x86: -208 unix x64: -408 unix nanbox: -248 stm32: -12 cc3200: -24 esp8266: -96 esp32: -44
2018-05-21py/emitbc: Avoid undefined behavior calling memset() with NULL 1st arg.Jeff Epler
Calling memset(NULL, value, 0) is not standards compliant so we must add an explicit check that emit->label_offsets is indeed not NULL before calling memset (this pointer will be NULL on the first pass of the parse tree and it's more logical / safer to check this pointer rather than check that the pass is not the first one). Code sanitizers will warn if NULL is passed as the first value to memset, and compilers may optimise the code based on the knowledge that any pointer passed to memset is guaranteed not to be NULL.
2018-02-14py/emitglue: When assigning bytecode only pass bytecode len if needed.Damien George
Most embedded targets will have this bit of the code disabled, saving a small amount of code space.
2017-12-08py/{emitbc,asmbase}: Only clear emit labels to -1 when in debug mode.Damien George
Clearing the labels to -1 is purely a debugging measure. For release builds there is no need to do it as the label offset table should always have the correct value assigned.
2017-09-13py/emitbc: Remove stray semicolon in outer scope.Damien George
2017-07-31all: Use the name MicroPython consistently in commentsAlexander Steffen
There were several different spellings of MicroPython present in comments, when there should be only one.
2017-07-07py,extmod: Some casts and minor refactors to quiet compiler warnings.Tom Collins
2017-05-25py/emitbc: Fix bug with BC emitter computing Python stack size.Damien George
Previous to this patch the mp_emit_bc_adjust_stack_size function would adjust the current stack size but would not increase the maximum stack size if the current size went above it. This meant that certain Python code (eg a try-finally block with no statements inside it) would not have enough Python stack allocated to it. This patch fixes the problem by always checking if the current stack size goes above the maximum, and adjusting the latter if it does.
2017-04-22py: Add LOAD_SUPER_METHOD bytecode to allow heap-free super meth calls.Damien George
This patch allows the following code to run without allocating on the heap: super().foo(...) Before this patch such a call would allocate a super object on the heap and then load the foo method and call it right away. The super object is only needed to perform the lookup of the method and not needed after that. This patch makes an optimisation to allocate the super object on the C stack and discard it right after use. Changes in code size due to this patch are: bare-arm: +128 minimal: +232 unix x64: +416 unix nanbox: +364 stmhal: +184 esp8266: +340 cc3200: +128
2017-03-23py: Define and use MP_OBJ_ITER_BUF_NSLOTS to get size of stack iter buf.Damien George
It improves readability of code and reduces the chance to make a mistake. This patch also fixes a bug with nan-boxing builds by rounding up the calculation of the new NSLOTS variable, giving the correct number of slots (being 4) even if mp_obj_t is larger than the native machine size.
2017-02-16py: Remove unused "use_stack" argument from for_iter_end emit function.Damien George
2017-02-16py: Optimise storage of iterator so it takes only 4 slots on Py stack.Damien George
2017-02-16py: Make FOR_ITER opcode pop 1+4 slots from the stack when finished.Damien George
The extra 4 slots correspond to the iterator object stored on the stack.
2017-02-16py: Allow bytecode/native to put iter_buf on stack for simple for loops.Damien George
So that the "for x in it: ..." statement can now work without using the heap (so long as the iterator argument fits in an iter_buf structure).
2017-02-10py/emitbc: Produce correct line number info for large bytecode chunks.Damien George
Previous to this patch, for large chunks of bytecode that originated from a single source-code line, the bytecode-line mapping would generate something like (for 42 bytecode bytes and 1 line): BC_SKIP=31 LINE_SKIP=1 BC_SKIP=11 LINE_SKIP=0 This would mean that any errors in the last 11 bytecode bytes would be reported on the following line. This patch fixes it to generate instead: BC_SKIP=31 LINE_SKIP=0 BC_SKIP=11 LINE_SKIP=1
2016-10-31py: remove asserts that are always true in emitbc.cPavol Rusnak
2016-09-27py/emitbc: Remove/refactor unreachable code, to improve coverage.Damien George
2016-09-27py: Only store the exception instance on Py stack in bytecode try block.Damien George
When an exception is raised and is to be handled by the VM, it is stored on the Python value stack so the bytecode can access it. CPython stores 3 objects on the stack for each exception: exc type, exc instance and traceback. uPy followed this approach, but it turns out not to be necessary. Instead, it is enough to store just the exception instance on the Python value stack. The only place where the 3 values are needed explicitly is for the __exit__ handler of a with-statement context, but for these cases the 3 values can be extracted from the single exception instance. This patch removes the need to store 3 values on the stack, and instead just stores the exception instance. Code size is reduced by about 50-100 bytes, the compiler and VM are slightly simpler, generate bytecode is smaller (by 2 bytes for each try block), and the Python value stack is reduced in size for functions that handle exceptions.
2016-09-19py: Combine 3 comprehension opcodes (list/dict/set) into 1.Damien George
With the previous patch combining 3 emit functions into 1, it now makes sense to also combine the corresponding VM opcodes, which is what this patch does. This eliminates 2 opcodes which simplifies the VM and reduces code size, in bytes: bare-arm:44, minimal:64, unix(NDEBUG,x86-64):272, stmhal:92, esp8266:200. Profiling (with a simple script that creates many list/dict/set comprehensions) shows no measurable change in performance.
2016-09-19py: Combine 3 comprehension emit functions (list/dict/set) into 1.Damien George
The 3 kinds of comprehensions are similar enough that merging their emit functions reduces code size. Decreases in code size in bytes are: bare-arm:24, minimal:96, unix(NDEBUG,x86-64):328, stmhal:80, esp8266:76.
2016-04-07py: Combine continuous block of emit steps into with_cleanup emit call.Damien George
Because different emitters need to handle with-cleanup in different ways.
2016-02-25py: Add MICROPY_DYNAMIC_COMPILER option to config compiler at runtime.Damien George
This new compile-time option allows to make the bytecode compiler configurable at runtime by setting the fields in the mp_dynamic_compiler structure. By using this feature, the compiler can generate bytecode that targets any MicroPython runtime/VM, regardless of the host and target compile-time settings. Options so far that fall under this dynamic setting are: - maximum number of bits that a small int can hold; - whether caching of lookups is used in the bytecode; - whether to use unicode strings or not (lexer behaviour differs, and therefore generated string constants differ).
2015-12-18py: Add MICROPY_ENABLE_COMPILER and MICROPY_PY_BUILTINS_EVAL_EXEC opts.Damien George
MICROPY_ENABLE_COMPILER can be used to enable/disable the entire compiler, which is useful when only loading of pre-compiled bytecode is supported. It is enabled by default. MICROPY_PY_BUILTINS_EVAL_EXEC controls support of eval and exec builtin functions. By default they are only included if MICROPY_ENABLE_COMPILER is enabled. Disabling both options saves about 40k of code size on 32-bit x86.
2015-12-10py: Make UNARY_OP_NOT a first-class op, to agree with Py not semantics.Damien George
Fixes #1684 and makes "not" match Python semantics. The code is also simplified (the separate MP_BC_NOT opcode is removed) and the patch saves 68 bytes for bare-arm/ and 52 bytes for minimal/. Previously "not x" was implemented as !mp_unary_op(x, MP_UNARY_OP_BOOL), so any given object only needs to implement MP_UNARY_OP_BOOL (and the VM had a special opcode to do the ! bit). With this patch "not x" is implemented as mp_unary_op(x, MP_UNARY_OP_NOT), but this operation is caught at the start of mp_unary_op and dispatched as !mp_obj_is_true(x). mp_obj_is_true has special logic to test for truthness, and is the correct way to handle the not operation.
2015-11-29py: Wrap all obj-ptr conversions in MP_OBJ_TO_PTR/MP_OBJ_FROM_PTR.Damien George
This allows the mp_obj_t type to be configured to something other than a pointer-sized primitive type. This patch also includes additional changes to allow the code to compile when sizeof(mp_uint_t) != sizeof(void*), such as using size_t instead of mp_uint_t, and various casts.