1. 20 Feb, 2018 1 commit
  2. 04 Feb, 2018 1 commit
    • Damien George's avatar
      py/compile: Combine compiler-opt of 2 and 3 tuple-to-tuple assignment. · 253f2bd7
      Damien George authored
      This patch combines the compiler optimisation code for double and triple
      tuple-to-tuple assignment, taking it from two separate if-blocks to one
      combined if-block.  This can be done because the code for both of these
      optimisations has a lot in common.  Combining them together reduces code
      size for ports that have the triple-tuple optimisation enabled (and doesn't
      change code size for ports that have it disabled).
  3. 11 Dec, 2017 1 commit
  4. 01 Nov, 2017 1 commit
    • Damien George's avatar
      py/compile: Use alloca instead of qstr_build when compiling import name. · 487dbdb2
      Damien George authored
      The technique of using alloca is how dotted import names are composed in
      mp_import_from and mp_builtin___import__, so use the same technique in the
      compiler.  This puts less pressure on the heap (only the stack is used if
      the qstr already exists, and if it doesn't exist then the standard qstr
      block memory is used for the new qstr rather than a separate chunk of the
      heap) and reduces overall code size.
  5. 21 Aug, 2017 1 commit
  6. 31 Jul, 2017 1 commit
  7. 09 Jul, 2017 1 commit
  8. 05 Jul, 2017 2 commits
  9. 22 Jun, 2017 2 commits
    • Damien George's avatar
      py/compile: Optimise emitter label indices to save a word of heap. · d94bc675
      Damien George authored
      Previous to this patch, a label with value "0" was used to indicate an
      invalid label, but that meant a wasted word (at slot 0) in the array of
      label offsets.  This patch adjusts the label indices so the first one
      starts at 0, and the maximum value indicates an invalid label.
    • Damien George's avatar
      py/compile: Fix bug with break/continue in else of optimised for-range. · 4c5f1083
      Damien George authored
      This patch fixes a bug whereby the Python stack was not correctly reset if
      there was a break/continue statement in the else black of an optimised
      for-range loop.
      For example, in the following code the "j" variable from the inner for loop
      was not being popped off the Python stack:
          for i in range(4):
              for j in range(4):
      This is now fixed with this patch.
  10. 14 Jun, 2017 1 commit
    • Damien George's avatar
      py/compile: Raise SyntaxError if positional args are given after */**. · 1e70fda6
      Damien George authored
      In CPython 3.4 this raises a SyntaxError.  In CPython 3.5+ having a
      positional after * is allowed but uPy has the wrong semantics and passes
      the arguments in the incorrect order.  To prevent incorrect use of a
      function going unnoticed it is important to raise the SyntaxError in uPy,
      until the behaviour is fixed to follow CPython 3.5+.
  11. 29 May, 2017 1 commit
  12. 22 Apr, 2017 6 commits
    • Damien George's avatar
      py: Add LOAD_SUPER_METHOD bytecode to allow heap-free super meth calls. · dd11af20
      Damien George authored
      This patch allows the following code to run without allocating on the heap:
      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
    • Damien George's avatar
      py/compile: Refactor handling of special super() call. · 5335942b
      Damien George authored
      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
    • Damien George's avatar
      py/compile: Don't do unnecessary check if iter parse node is a struct. · 0dd6a59c
      Damien George authored
      If we get to this point in the code then pn_iter is guaranteed to be a
    • Damien George's avatar
      py/compile: Add COMP_RETURN_IF_EXPR option to enable return-if-else opt. · ae54fbf1
      Damien George authored
      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.
    • Damien George's avatar
      py/compile: Extract parse-node kind at start of func for efficiency. · 40b40ffc
      Damien George authored
      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
    • Damien George's avatar
      py/compile: Don't do unnecessary check if parse node is a struct. · fa03bbf0
      Damien George authored
      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.
  13. 05 Apr, 2017 1 commit
  14. 29 Mar, 2017 3 commits
  15. 27 Mar, 2017 1 commit
  16. 23 Mar, 2017 1 commit
  17. 24 Feb, 2017 1 commit
    • Damien George's avatar
      py: Create str/bytes objects in the parser, not the compiler. · 5255255f
      Damien George authored
      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.
  18. 17 Feb, 2017 1 commit
    • Damien George's avatar
      py: Do adjacent str/bytes literal concatenation in lexer, not compiler. · 534b7c36
      Damien George authored
      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
  19. 16 Feb, 2017 6 commits
  20. 19 Dec, 2016 1 commit
  21. 09 Dec, 2016 5 commits
    • Damien George's avatar
      py/emitinline: Move common code for end of final pass to compiler. · e920bab9
      Damien George authored
      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.
    • Damien George's avatar
      py/emitinline: Move inline-asm align and data methods to compiler. · dd53b121
      Damien George authored
      These are generic methods that don't depend on the architecture and so
      can be handled directly by the compiler.
    • Damien George's avatar
      py: Add inline Xtensa assembler. · f76b1bfa
      Damien George authored
      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):
          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.
    • Damien George's avatar
      py: Allow inline-assembler emitter to be generic. · ad297a19
      Damien George authored
      This patch refactors some code so that it is easier to integrate new
      inline assemblers for different architectures other than ARM Thumb.
    • Damien George's avatar
      py: Integrate Xtensa assembler into native emitter. · 8e5aced1
      Damien George authored
      The config option MICROPY_EMIT_XTENSA can now be enabled to target the
      Xtensa architecture with @micropython.native and @micropython.viper
  22. 07 Dec, 2016 1 commit