summaryrefslogtreecommitdiffstatshomepage
path: root/py/compile.c
Commit message (Collapse)AuthorAge
* various: Spelling fixesVille Skyttä2017-05-29
|
* py: Add LOAD_SUPER_METHOD bytecode to allow heap-free super meth calls.Damien George2017-04-22
| | | | | | | | | | | | | | | | | | | | | | 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
* py/compile: Refactor handling of special super() call.Damien George2017-04-22
| | | | | | | | | | | | | | | | | | | This patch refactors the handling of the special super() call within the compiler. It removes the need for a global (to the compiler) state variable which keeps track of whether the subject of an expression is super. The handling of super() is now done entirely within one function, which makes the compiler a bit cleaner and allows to easily add more optimisations to super calls. Changes to the code size are: bare-arm: +12 minimal: +0 unix x64: +48 unix nanbox: -16 stmhal: +4 cc3200: +0 esp8266: -56
* py/compile: Don't do unnecessary check if iter parse node is a struct.Damien George2017-04-22
| | | | | If we get to this point in the code then pn_iter is guaranteed to be a struct.
* py/compile: Add COMP_RETURN_IF_EXPR option to enable return-if-else opt.Damien George2017-04-22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With this optimisation enabled the compiler optimises the if-else expression within a return statement. The optimisation reduces bytecode size by 2 bytes for each use of such a return-if-else statement. Since such a statement is not often used, and costs bytes for the code, the feature is disabled by default. For example the following code: def f(x): return 1 if x else 2 compiles to this bytecode with the optimisation disabled (left column is bytecode offset in bytes): 00 LOAD_FAST 0 01 POP_JUMP_IF_FALSE 8 04 LOAD_CONST_SMALL_INT 1 05 JUMP 9 08 LOAD_CONST_SMALL_INT 2 09 RETURN_VALUE and to this bytecode with the optimisation enabled: 00 LOAD_FAST 0 01 POP_JUMP_IF_FALSE 6 04 LOAD_CONST_SMALL_INT 1 05 RETURN_VALUE 06 LOAD_CONST_SMALL_INT 2 07 RETURN_VALUE So the JUMP to RETURN_VALUE is optimised and replaced by RETURN_VALUE, saving 2 bytes and making the code a bit faster.
* py/compile: Extract parse-node kind at start of func for efficiency.Damien George2017-04-22
| | | | | | Otherwise the type of parse-node and its kind has to be re-extracted multiple times. This optimisation reduces code size by a bit (16 bytes on bare-arm).
* py/compile: Don't do unnecessary check if parse node is a struct.Damien George2017-04-22
| | | | | PN_atom_expr_normal parse nodes always have structs for their second sub-node, so simplify the check for the sub-node kind to save code size.
* py: Raise a ValueError if range() step is zero.Damien George2017-04-05
| | | | | Following CPython. Otherwise one gets either an infinite loop (if code is optimised by the uPy compiler) or possibly a divide-by-zero CPU exception.
* py/compile: Provide terse error message for invalid dict/set literals.Damien George2017-03-29
|
* py: Shorten a couple of error messages.Damien George2017-03-29
|
* py/compile: Simplify syntax-error messages for illegal assignments.Damien George2017-03-29
| | | | | | | | With this patch all illegal assignments are reported as "can't assign to expression". Before the patch there were special cases for a literal on the LHS, and for augmented assignments (eg +=), but it seems a waste of bytes (and there are lots of bytes used in error messages) to spend on distinguishing such errors which a user will rarely encounter.
* py/compile: When compiling super(), handle closed-over self variable.Damien George2017-03-27
| | | | | | The self variable may be closed-over in the function, and in that case the call to super() should load the contents of the closure cell using LOAD_DEREF (before this patch it would just load the cell directly).
* py: Define and use MP_OBJ_ITER_BUF_NSLOTS to get size of stack iter buf.Damien George2017-03-23
| | | | | | | | 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.
* py: Create str/bytes objects in the parser, not the compiler.Damien George2017-02-24
| | | | | | | | | | | | | | | | | | Previous to this patch any non-interned str/bytes objects would create a special parse node that held a copy of the str/bytes data. Then in the compiler this data would be turned into a str/bytes object. This actually lead to 2 copies of the data, one in the parse node and one in the object. The parse node's copy of the data would be freed at the end of the compile stage but nevertheless it meant that the peak memory usage of the parse/compile stage was higher than it needed to be (by an amount equal to the number of bytes in all the non-interned str/bytes objects). This patch changes the behaviour so that str/bytes objects are created directly in the parser and the object stored in a const-object parse node (which already exists for bignum, float and complex const objects). This reduces peak RAM usage of the parse/compile stage, simplifies the parser and compiler, and reduces code size by about 170 bytes on Thumb2 archs, and by about 300 bytes on Xtensa archs.
* py: Do adjacent str/bytes literal concatenation in lexer, not compiler.Damien George2017-02-17
| | | | | | | | | | | | | | | | | | | | | It's much more efficient in RAM and code size to do implicit literal string concatenation in the lexer, as opposed to the compiler. RAM usage is reduced because the concatenation can be done right away in the tokeniser by just accumulating the string/bytes literals into the lexer's vstr. Prior to this patch adjacent strings/bytes would create a parse tree (one node per string/bytes) and then in the compiler a whole new chunk of memory was allocated to store the concatenated string, which used more than double the memory compared to just accumulating in the lexer. This patch also significantly reduces code size: bare-arm: -204 minimal: -204 unix x64: -328 stmhal: -208 esp8266: -284 cc3200: -224
* py/grammar: Group no-compile grammar rules together to shrink tables.Damien George2017-02-16
| | | | | | | | | | | | | | | | | | | | | | Grammar rules have 2 variants: ones that are attached to a specific compile function which is called to compile that grammar node, and ones that don't have a compile function and are instead just inspected to see what form they take. In the compiler there is a table of all grammar rules, with each entry having a pointer to the associated compile function. Those rules with no compile function have a null pointer. There are 120 such rules, so that's 120 words of essentially wasted code space. By grouping together the compile vs no-compile rules we can put all the no-compile rules at the end of the list of rules, and then we don't need to store the null pointers. We just have a truncated table and it's guaranteed that when indexing this table we only index the first half, the half with populated pointers. This patch implements such a grouping by having a specific macro for the compile vs no-compile grammar rules (DEF_RULE vs DEF_RULE_NC). It saves around 460 bytes of code on 32-bit archs.
* py/compile: Optimise list/dict/set comprehensions to use stack iter.Damien George2017-02-16
|
* py: Remove unused "use_stack" argument from for_iter_end emit function.Damien George2017-02-16
|
* py: Optimise storage of iterator so it takes only 4 slots on Py stack.Damien George2017-02-16
|
* py: Make FOR_ITER opcode pop 1+4 slots from the stack when finished.Damien George2017-02-16
| | | | The extra 4 slots correspond to the iterator object stored on the stack.
* py: Allow bytecode/native to put iter_buf on stack for simple for loops.Damien George2017-02-16
| | | | | 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).
* py/compile: Add an extra pass for Xtensa inline assembler.Damien George2016-12-19
| | | | | It needs an extra pass to compute the size of the constant table for the l32r instructions.
* py/emitinline: Move common code for end of final pass to compiler.Damien George2016-12-09
| | | | | | This patch moves some common code from the individual inline assemblers to the compiler, the code that calls the emit-glue to assign the machine code to the functions scope.
* py/emitinline: Move inline-asm align and data methods to compiler.Damien George2016-12-09
| | | | | These are generic methods that don't depend on the architecture and so can be handled directly by the compiler.
* py: Add inline Xtensa assembler.Damien George2016-12-09
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds the MICROPY_EMIT_INLINE_XTENSA option, which, when enabled, allows the @micropython.asm_xtensa decorator to be used. The following opcodes are currently supported (ax is a register, a0-a15): ret_n() callx0(ax) j(label) jx(ax) beqz(ax, label) bnez(ax, label) mov(ax, ay) movi(ax, imm) # imm can be full 32-bit, uses l32r if needed and_(ax, ay, az) or_(ax, ay, az) xor(ax, ay, az) add(ax, ay, az) sub(ax, ay, az) mull(ax, ay, az) l8ui(ax, ay, imm) l16ui(ax, ay, imm) l32i(ax, ay, imm) s8i(ax, ay, imm) s16i(ax, ay, imm) s32i(ax, ay, imm) l16si(ax, ay, imm) addi(ax, ay, imm) ball(ax, ay, label) bany(ax, ay, label) bbc(ax, ay, label) bbs(ax, ay, label) beq(ax, ay, label) bge(ax, ay, label) bgeu(ax, ay, label) blt(ax, ay, label) bnall(ax, ay, label) bne(ax, ay, label) bnone(ax, ay, label) Upon entry to the assembly function the registers a0, a12, a13, a14 are pushed to the stack and the stack pointer (a1) decreased by 16. Upon exit, these registers and the stack pointer are restored, and ret.n is executed to return to the caller (caller address is in a0). Note that the ABI for the Xtensa emitters is non-windowing.
* py: Allow inline-assembler emitter to be generic.Damien George2016-12-09
| | | | | This patch refactors some code so that it is easier to integrate new inline assemblers for different architectures other than ARM Thumb.
* py: Integrate Xtensa assembler into native emitter.Damien George2016-12-09
| | | | | | The config option MICROPY_EMIT_XTENSA can now be enabled to target the Xtensa architecture with @micropython.native and @micropython.viper decorators.
* py/compile: Simplify configuration of native emitter.Damien George2016-12-07
|
* py/compile: Remove comment about TODO for short circuiting for if-stmt.Damien George2016-11-26
| | | | | Short circuiting is handled correctly by c_if_cond, and constants within short-circuit expressions are optimised by the parser.
* py/parse: Make mp_parse_node_new_leaf an inline function.Damien George2016-11-15
| | | | | | It is split into 2 functions, one to make small ints and the other to make a non-small-int leaf node. This reduces code size by 32 bytes on bare-arm, 64 bytes on unix (x64-64) and 144 bytes on stmhal.
* py/parse: Move function to check for const parse node to parse.[ch].Damien George2016-11-15
|
* py/compile: Remove debugging code for compiler dispatch.Damien George2016-10-12
| | | | | It was a relic from the days of developing the compiler and is no longer needed, and it's impossible to trigger via a test.
* py/compile: Remove unreachable code.Damien George2016-10-11
|
* py/compile: Fix typo when checking for parse-node kind.Damien George2016-09-30
|
* py/scope: Factor common code to find locals and close over them.Damien George2016-09-30
| | | | Saves 50-100 bytes of code.
* py/scope: Use lookup-table to determine a scope's simple name.Damien George2016-09-30
| | | | Generates slightly smaller and more efficient code.
* py/compile: Fix async-for/async-with to work with simpler exc on stack.Damien George2016-09-28
| | | | | There is now just the exception instance on the stack when an exception is raised, not the full (type, exc, traceback).
* py: Only store the exception instance on Py stack in bytecode try block.Damien George2016-09-27
| | | | | | | | | | | | | | | | | | | | 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.
* py: Combine 3 comprehension emit functions (list/dict/set) into 1.Damien George2016-09-19
| | | | | | 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.
* py/compile: Don't compile assert statements when optimisations enabled.Damien George2016-08-26
| | | | As per CPython.
* py: Declare constant data as properly constant.Damien George2016-05-20
| | | | | Otherwise some compilers (eg without optimisation) will put this read-only data in RAM instead of ROM.
* py: Fix constant folding and inline-asm to work with new async grammar.Damien George2016-04-13
|
* py: add async/await/async for/async with syntaxpohmelie2016-04-13
| | | | | | | | They are sugar for marking function as generator, "yield from" and pep492 python "semantically equivalents" respectively. @dpgeorge was the original author of this patch, but @pohmelie made changes to implement `async for` and `async with`.
* py: Implement basic with support in native emitter.Damien George2016-04-07
|
* py: Combine continuous block of emit steps into with_cleanup emit call.Damien George2016-04-07
| | | | Because different emitters need to handle with-cleanup in different ways.
* py: Don't allocate an extra parse node for power exponent.Damien George2016-03-16
| | | | | | Previous to this patch, the "**b" in "a**b" had its own parse node with just one item (the "b"). Now, the "b" is just the last element of the power parse-node. This saves (a tiny bit of) RAM when compiling.
* py: Add MICROPY_DYNAMIC_COMPILER option to config compiler at runtime.Damien George2016-02-25
| | | | | | | | | | | | | | 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).
* py/inlineasm: Add ability to specify return type of asm_thumb funcs.Damien George2016-01-27
| | | | | | | | | | Supported return types are: object, bool, int, uint. For example: @micropython.asm_thumb def foo(r0, r1) -> uint: add(r0, r0, r1)
* py/parse: Optimise away parse node that's just parenthesis around expr.Damien George2016-01-07
| | | | | | | | | | Before this patch, (x+y)*z would be parsed to a tree that contained a redundant identity parse node corresponding to the parenthesis. With this patch such nodes are optimised away, which reduces memory requirements for expressions with parenthesis, and simplifies the compiler because it doesn't need to handle this identity case. A parenthesis parse node is still needed for tuples.
* py: Add MICROPY_ENABLE_COMPILER and MICROPY_PY_BUILTINS_EVAL_EXEC opts.Damien George2015-12-18
| | | | | | | | | | | | 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.