summaryrefslogtreecommitdiff
path: root/py/emitnx86.c
AgeCommit message (Collapse)Author
2018-10-01py/emitnative: Implement yield and yield-from in native emitter.Damien George
This commit adds first class support for yield and yield-from in the native emitter, including send and throw support, and yields enclosed in exception handlers (which requires pulling down the NLR stack before yielding, then rebuilding it when resuming). This has been fully tested and is working on unix x86 and x86-64, and stm32. Also basic tests have been done with the esp8266 port. Performance of existing native code is unchanged.
2018-09-15py: Make viper functions have the same entry signature as native.Damien George
This commit makes viper functions have the same signature as native functions, at the level of the emitter/assembler. This means that viper functions can now be wrapped in the same uPy object as native functions. Viper functions are now responsible for parsing their arguments (before it was done by the runtime), and this makes calling them more efficient (in most cases) because the viper entry code can be custom generated to suit the signature of the function. This change also opens the way forward for viper functions to take arbitrary numbers of arguments, and for them to handle globals correctly, among other things.
2018-09-13py: Fix native functions so they run with their correct globals context.Damien George
Prior to this commit a function compiled with the native decorator @micropython.native would not work correctly when accessing global variables, because the globals dict was not being set upon function entry. This commit fixes this problem by, upon function entry, setting as the current globals dict the globals dict context the function was defined within, as per normal Python semantics, and as bytecode does. Upon function exit the original globals dict is restored. In order to restore the globals dict when an exception is raised the native function must guard its internals with an nlr_push/nlr_pop pair. Because this push/pop is relatively expensive, in both C stack usage for the nlr_buf_t and CPU execution time, the implementation here optimises things as much as possible. First, the compiler keeps track of whether a function even needs to access global variables. Using this information the native emitter then generates three different kinds of code: 1. no globals used, no exception handlers: no nlr handling code and no setting of the globals dict. 2. globals used, no exception handlers: an nlr_buf_t is allocated on the C stack but it is not used if the globals dict is unchanged, saving execution time because nlr_push/nlr_pop don't need to run. 3. function has exception handlers, may use globals: an nlr_buf_t is allocated and nlr_push/nlr_pop are always called. In the end, native functions that don't access globals and don't have exception handlers will run more efficiently than those that do. Fixes issue #1573.
2018-09-04py/emitnative: Add support for return/break/continue in try and with.Damien George
This patch adds full support for unwinding jumps to the native emitter. This means that return/break/continue can be used in try-except, try-finally and with statements. For code that doesn't use unwinding jumps there is almost no overhead added to the generated code.
2018-08-17py/emitnx86: Fix number of args passed to mp_setup_code_state, 4 not 5.Damien George
2018-08-16py/emitnative: Optimise and improve exception handling in native code.Damien George
Prior to this patch, native code would use a full nlr_buf_t for each exception handler (try-except, try-finally, with). For nested exception handlers this would use a lot of C stack and be rather inefficient. This patch changes how exceptions are handled in native code by setting up only a single nlr_buf_t context for the entire function, and then manages a state machine (using the PC) to work out which exception handler to run when an exception is raised by an nlr_jump. This keeps the C stack usage at a constant level regardless of the depth of Python exception blocks. The patch also fixes an existing bug when local variables are written to within an exception handler, then their value was incorrectly restored if an exception was raised (since the nlr_jump would restore register values, back to the point of the nlr_push). And it also gets nested try-finally+with working with the viper emitter. Broadly speaking, efficiency of executing native code that doesn't use any exception blocks is unchanged, and emitted code size is only slightly increased for such function. C stack usage of all native functions is either equal or less than before. Emitted code size for native functions that use exception blocks is increased by roughly 10% (due in part to fixing of above-mentioned bugs). But, most importantly, this patch allows to implement more Python features in native code, like unwind jumps and yielding from within nested exception blocks.
2018-05-04py/emitnx86: Fix 32-bit x86 native emitter build by including header.Damien George
2018-04-10py: Refactor how native emitter code is compiled with a file per arch.Damien George
Instead of emitnative.c having configuration code for each supported architecture, and then compiling this file multiple times with different macros defined, this patch adds a file per architecture with the necessary code to configure the native emitter. These files then #include the emitnative.c file. This simplifies emitnative.c (which is already very large), and simplifies the build system because emitnative.c no longer needs special handling for compilation and qstr extraction.