Skip to content
  • Damien George's avatar
    py: Tidy up variables in VM, probably fixes subtle bugs. · 66ae8c9f
    Damien George authored
    Things get tricky when using the nlr code to catch exceptions.  Need to
    ensure that the variables (stack layout) in the exception handler are
    the same as in the bit protected by the exception handler.
    Prior to this patch there were a few bugs.  1) The constant
    mp_const_MemoryError_obj was being preloaded to a specific location on
    the stack at the start of the function.  But this location on the stack
    was being overwritten in the opcode loop (since it didn't think that
    variable would ever be referenced again), and so when an exception
    occurred, the variable holding the address of MemoryError was corrupt.
    2) The FOR_ITER opcode detection in the exception handler used sp, which
    may or may not contain the right value coming out of the main opcode
    With this patch there is a clear separation of variables used in the
    opcode loop and in the exception handler (should fix issue (2) above).
    Furthermore, nlr_raise is no longer used in the opcode loop.  Instead,
    it jumps directly into the exception handler.  This tells the C compiler
    more about the possible code flow, and means that it should have the
    same stack layout for the exception handler.  This should fix issue (1)
    above.  Indeed, the generated (ARM) assembler has been checked explicitly,
    and with 'goto exception_handler', the problem with &MemoryError is
    This may now fix problems with rge-sm, and probably many other subtle
    bugs yet to show themselves.  Incidentally, rge-sm now passes on
    pyboard (with a reduced range of integration)!
    Main lesson: nlr is tricky.  Don't use nlr_push unless you know what you
    are doing!  Luckily, it's not used in many places.  Using nlr_raise/jump
    is fine.