summaryrefslogtreecommitdiffstatshomepage
path: root/py/nativeglue.c
Commit message (Collapse)AuthorAge
* py/dynruntime: Export mp_load_method_maybe and mp_arg_parse_all* funcs.Brian Pugh2024-05-24
| | | | | | | Also define `mp_type_bytearray`. These all help to write native modules. Signed-off-by: Brian Pugh <bnp117@gmail.com> Signed-off-by: Damien George <damien@micropython.org>
* py/dynruntime: Add mp_obj_exception_init function to create C exception.Damien George2024-05-23
| | | | Signed-off-by: Damien George <damien@micropython.org>
* py/dynruntime: Add mp_binary_get_size/get_val_array/set_val_array.Damien George2024-03-28
| | | | | | | These are needed to read/write array.array objects, which is useful in native code to provide fast extensions that work with big arrays of data. Signed-off-by: Damien George <damien@micropython.org>
* all: Remove the "STATIC" macro and just use "static" instead.Angus Gratton2024-03-07
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The STATIC macro was introduced a very long time ago in commit d5df6cd44a433d6253a61cb0f987835fbc06b2de. The original reason for this was to have the option to define it to nothing so that all static functions become global functions and therefore visible to certain debug tools, so one could do function size comparison and other things. This STATIC feature is rarely (if ever) used. And with the use of LTO and heavy inline optimisation, analysing the size of individual functions when they are not static is not a good representation of the size of code when fully optimised. So the macro does not have much use and it's simpler to just remove it. Then you know exactly what it's doing. For example, newcomers don't have to learn what the STATIC macro is and why it exists. Reading the code is also less "loud" with a lowercase static. One other minor point in favour of removing it, is that it stops bugs with `STATIC inline`, which should always be `static inline`. Methodology for this commit was: 1) git ls-files | egrep '\.[ch]$' | \ xargs sed -Ei "s/(^| )STATIC($| )/\1static\2/" 2) Do some manual cleanup in the diff by searching for the word STATIC in comments and changing those back. 3) "git-grep STATIC docs/", manually fixed those cases. 4) "rg -t python STATIC", manually fixed codegen lines that used STATIC. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
* py/emitglue: Introduce mp_proto_fun_t as a more general mp_raw_code_t.Damien George2024-02-16
| | | | | | | | | | Allows bytecode itself to be used instead of an mp_raw_code_t in the simple and common cases of a bytecode function without any children. This can be used to further reduce frozen code size, and has the potential to optimise other areas like importing. Signed-off-by: Damien George <damien@micropython.org>
* py/dynruntime: Add mp_get_buffer.Damien George2023-10-16
| | | | Signed-off-by: Damien George <damien@micropython.org>
* py/dynruntime.h: Implement MP_OBJ_NEW_QSTR.Jim Mussared2023-09-01
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Because mpy_ld.py doesn't know the target object representation, it emits instances of `MP_OBJ_NEW_QSTR(MP_QSTR_Foo)` as const string objects, rather than qstrs. However this doesn't work for map keys (e.g. for a locals dict) because the map has all_keys_are_qstrs flag is set (and also auto-complete requires the map keys to be qstrs). Instead, emit them as regular qstrs, and make a functioning MP_OBJ_NEW_QSTR function available (via `native_to_obj`, also used for e.g. making integers). Remove the code from mpy_ld.py to emit qstrs as constant strings, but leave behind the scaffold to emit constant objects in case we want to do use this in the future. Strictly this should be a .mpy sub-version bump, even though the function table isn't changing, it does lead to a change in behavior for a new .mpy running against old MicroPython. `mp_native_to_obj` will incorrectly return the qstr value directly as an `mp_obj_t`, leading to unexpected results. But given that it's broken at the moment, it seems unlikely that anyone is relying on this, so it's not work the other downsides of a sub-version bump (i.e. breaking pure-Python modules that use @native). The opposite case of running an old .mpy on new MicroPython is unchanged, and remains broken in exactly the same way. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
* py/bc: Provide separate code-state setup funcs for bytecode and native.Damien George2022-05-17
| | | | | | | | | | | | | mpy-cross will now generate native code based on the size of mp_code_state_native_t, and the runtime will use this struct to calculate the offset of the .state field. This makes native code generation and execution (which rely on this struct) independent to the settings MICROPY_STACKLESS and MICROPY_PY_SYS_SETTRACE, both of which change the size of the mp_code_state_t struct. Fixes issue #5059. Signed-off-by: Damien George <damien@micropython.org>
* py: Rework bytecode and .mpy file format to be mostly static data.Damien George2022-02-24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Background: .mpy files are precompiled .py files, built using mpy-cross, that contain compiled bytecode functions (and can also contain machine code). The benefit of using an .mpy file over a .py file is that they are faster to import and take less memory when importing. They are also smaller on disk. But the real benefit of .mpy files comes when they are frozen into the firmware. This is done by loading the .mpy file during compilation of the firmware and turning it into a set of big C data structures (the job of mpy-tool.py), which are then compiled and downloaded into the ROM of a device. These C data structures can be executed in-place, ie directly from ROM. This makes importing even faster because there is very little to do, and also means such frozen modules take up much less RAM (because their bytecode stays in ROM). The downside of frozen code is that it requires recompiling and reflashing the entire firmware. This can be a big barrier to entry, slows down development time, and makes it harder to do OTA updates of frozen code (because the whole firmware must be updated). This commit attempts to solve this problem by providing a solution that sits between loading .mpy files into RAM and freezing them into the firmware. The .mpy file format has been reworked so that it consists of data and bytecode which is mostly static and ready to run in-place. If these new .mpy files are located in flash/ROM which is memory addressable, the .mpy file can be executed (mostly) in-place. With this approach there is still a small amount of unpacking and linking of the .mpy file that needs to be done when it's imported, but it's still much better than loading an .mpy from disk into RAM (although not as good as freezing .mpy files into the firmware). The main trick to make static .mpy files is to adjust the bytecode so any qstrs that it references now go through a lookup table to convert from local qstr number in the module to global qstr number in the firmware. That means the bytecode does not need linking/rewriting of qstrs when it's loaded. Instead only a small qstr table needs to be built (and put in RAM) at import time. This means the bytecode itself is static/constant and can be used directly if it's in addressable memory. Also the qstr string data in the .mpy file, and some constant object data, can be used directly. Note that the qstr table is global to the module (ie not per function). In more detail, in the VM what used to be (schematically): qst = DECODE_QSTR_VALUE; is now (schematically): idx = DECODE_QSTR_INDEX; qst = qstr_table[idx]; That allows the bytecode to be fixed at compile time and not need relinking/rewriting of the qstr values. Only qstr_table needs to be linked when the .mpy is loaded. Incidentally, this helps to reduce the size of bytecode because what used to be 2-byte qstr values in the bytecode are now (mostly) 1-byte indices. If the module uses the same qstr more than two times then the bytecode is smaller than before. The following changes are measured for this commit compared to the previous (the baseline): - average 7%-9% reduction in size of .mpy files - frozen code size is reduced by about 5%-7% - importing .py files uses about 5% less RAM in total - importing .mpy files uses about 4% less RAM in total - importing .py and .mpy files takes about the same time as before The qstr indirection in the bytecode has only a small impact on VM performance. For stm32 on PYBv1.0 the performance change of this commit is: diff of scores (higher is better) N=100 M=100 baseline -> this-commit diff diff% (error%) bm_chaos.py 371.07 -> 357.39 : -13.68 = -3.687% (+/-0.02%) bm_fannkuch.py 78.72 -> 77.49 : -1.23 = -1.563% (+/-0.01%) bm_fft.py 2591.73 -> 2539.28 : -52.45 = -2.024% (+/-0.00%) bm_float.py 6034.93 -> 5908.30 : -126.63 = -2.098% (+/-0.01%) bm_hexiom.py 48.96 -> 47.93 : -1.03 = -2.104% (+/-0.00%) bm_nqueens.py 4510.63 -> 4459.94 : -50.69 = -1.124% (+/-0.00%) bm_pidigits.py 650.28 -> 644.96 : -5.32 = -0.818% (+/-0.23%) core_import_mpy_multi.py 564.77 -> 581.49 : +16.72 = +2.960% (+/-0.01%) core_import_mpy_single.py 68.67 -> 67.16 : -1.51 = -2.199% (+/-0.01%) core_qstr.py 64.16 -> 64.12 : -0.04 = -0.062% (+/-0.00%) core_yield_from.py 362.58 -> 354.50 : -8.08 = -2.228% (+/-0.00%) misc_aes.py 429.69 -> 405.59 : -24.10 = -5.609% (+/-0.01%) misc_mandel.py 3485.13 -> 3416.51 : -68.62 = -1.969% (+/-0.00%) misc_pystone.py 2496.53 -> 2405.56 : -90.97 = -3.644% (+/-0.01%) misc_raytrace.py 381.47 -> 374.01 : -7.46 = -1.956% (+/-0.01%) viper_call0.py 576.73 -> 572.49 : -4.24 = -0.735% (+/-0.04%) viper_call1a.py 550.37 -> 546.21 : -4.16 = -0.756% (+/-0.09%) viper_call1b.py 438.23 -> 435.68 : -2.55 = -0.582% (+/-0.06%) viper_call1c.py 442.84 -> 440.04 : -2.80 = -0.632% (+/-0.08%) viper_call2a.py 536.31 -> 532.35 : -3.96 = -0.738% (+/-0.06%) viper_call2b.py 382.34 -> 377.07 : -5.27 = -1.378% (+/-0.03%) And for unix on x64: diff of scores (higher is better) N=2000 M=2000 baseline -> this-commit diff diff% (error%) bm_chaos.py 13594.20 -> 13073.84 : -520.36 = -3.828% (+/-5.44%) bm_fannkuch.py 60.63 -> 59.58 : -1.05 = -1.732% (+/-3.01%) bm_fft.py 112009.15 -> 111603.32 : -405.83 = -0.362% (+/-4.03%) bm_float.py 246202.55 -> 247923.81 : +1721.26 = +0.699% (+/-2.79%) bm_hexiom.py 615.65 -> 617.21 : +1.56 = +0.253% (+/-1.64%) bm_nqueens.py 215807.95 -> 215600.96 : -206.99 = -0.096% (+/-3.52%) bm_pidigits.py 8246.74 -> 8422.82 : +176.08 = +2.135% (+/-3.64%) misc_aes.py 16133.00 -> 16452.74 : +319.74 = +1.982% (+/-1.50%) misc_mandel.py 128146.69 -> 130796.43 : +2649.74 = +2.068% (+/-3.18%) misc_pystone.py 83811.49 -> 83124.85 : -686.64 = -0.819% (+/-1.03%) misc_raytrace.py 21688.02 -> 21385.10 : -302.92 = -1.397% (+/-3.20%) The code size change is (firmware with a lot of frozen code benefits the most): bare-arm: +396 +0.697% minimal x86: +1595 +0.979% [incl +32(data)] unix x64: +2408 +0.470% [incl +800(data)] unix nanbox: +1396 +0.309% [incl -96(data)] stm32: -1256 -0.318% PYBV10 cc3200: +288 +0.157% esp8266: -260 -0.037% GENERIC esp32: -216 -0.014% GENERIC[incl -1072(data)] nrf: +116 +0.067% pca10040 rp2: -664 -0.135% PICO samd: +844 +0.607% ADAFRUIT_ITSYBITSY_M4_EXPRESS As part of this change the .mpy file format version is bumped to version 6. And mpy-tool.py has been improved to provide a good visualisation of the contents of .mpy files. In summary: this commit changes the bytecode to use qstr indirection, and reworks the .mpy file format to be simpler and allow .mpy files to be executed in-place. Performance is not impacted too much. Eventually it will be possible to store such .mpy files in a linear, read-only, memory- mappable filesystem so they can be executed from flash/ROM. This will essentially be able to replace frozen code for most applications. Signed-off-by: Damien George <damien@micropython.org>
* all: Fix implicit floating point promotion.stijn2020-04-18
| | | | | | | | | | | | | Initially some of these were found building the unix coverage variant on MacOS because that build uses clang and has -Wdouble-promotion enabled, and clang performs more vigorous promotion checks than gcc. Additionally the codebase has been compiled with clang and msvc (the latter with warning level 3), and with MICROPY_FLOAT_IMPL_FLOAT to find the rest of the conversions. Fixes are implemented either as explicit casts, or by using the correct type, or by using one of the utility functions to handle floating point casting; these have been moved from nativeglue.c to the public API.
* all: Use MP_ERROR_TEXT for all error messages.Jim Mussared2020-04-05
|
* all: Reformat C and Python source code with tools/codeformat.py.Damien George2020-02-28
| | | | This is run with uncrustify 0.70.1, and black 19.10b0.
* py/nativeglue: Fix typo about where the native fun table enum is.Jim Mussared2020-01-27
|
* py/nativeglue: Use mp_const_X instead of &mp_const_X_obj.Damien George2020-01-12
|
* py/nativeglue: Add float new/get functions with both single and double.Damien George2019-12-12
|
* py/nativeglue: Add funcs/types to native glue table for dynamic runtime.Damien George2019-12-12
| | | | These allow discovery of symbols by native code that is loaded dynamically.
* py/nativeglue: Add new header file with native function table typedef.Damien George2019-12-12
|
* py/nativeglue: Remove unused mp_obj_new_cell from mp_fun_table.Damien George2019-11-01
| | | | It has been unused since 9988618e0e0f5c319e31b135d993e22efb593093
* py/emitnative: Add support for using setjmp with native emitter.Damien George2019-10-05
| | | | | To enable this feature the N_NLR_SETJMP macro should be set to 1 before including py/emitnative.c.
* py/nativeglue: Make mp_fun_table fixed size regardless of config.Damien George2019-09-26
| | | | | So that mpy files with native code will always work correctly, and raise an exception if a feature is used that is not supported by the runtime.
* py/bc0: Order opcodes into groups based on their size and format.Damien George2019-09-26
|
* py: Allow to pass in read-only buffers to viper and inline-asm funcs.Damien George2019-08-06
| | | | Fixes #4936.
* py: Define EMIT_MACHINE_CODE as EMIT_NATIVE || EMIT_INLINE_ASM.Jun Wu2019-06-28
| | | | | The combination MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM is used in many places, so define a new macro for it.
* py/nativeglue: Remove dependency on mp_fun_table in dyn-compiler mode.Damien George2019-05-29
| | | | | | | | | mpy-cross uses MICROPY_DYNAMIC_COMPILER and MICROPY_EMIT_NATIVE but does not actually need to execute native functions, and does not need mp_fun_table. This commit makes it so mp_fun_table and all its entries are not built when MICROPY_DYNAMIC_COMPILER is enabled, significantly reducing the size of the mpy-cross executable and allowing it to be built on more machines/OS's.
* py/nativeglue: Make private glue funs all static, remove commented code.Damien George2019-05-29
|
* py/native: Improve support for bool type in viper functions.Damien George2019-05-03
| | | | | Variables with type bool now act more like an int, and there is proper casting to/from Python objects.
* py/nativeglue: Rename native convert funs to match other native helpers.Damien George2019-03-14
|
* py: Move mp_native_type_from_qstr() from emitnative.c to nativeglue.c.Damien George2019-03-14
|
* py/emitnative: Put None/False/True in global native const table.Damien George2018-10-15
| | | | | | | So these constant objects can be loaded by dereferencing the REG_FUN_TABLE pointer instead of loading immediate values. This reduces the size of generated native code (when such constants are used), and means that pointers to these constants are no longer stored in the assembly code.
* py/emitnative: Implement yield and yield-from in native emitter.Damien George2018-10-01
| | | | | | | | | | | 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.
* py: Make viper functions have the same entry signature as native.Damien George2018-09-15
| | | | | | | | | | | | | | | 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.
* py: Fix native functions so they run with their correct globals context.Damien George2018-09-13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* py/emit: Merge build set/slice into existing build emit function.Damien George2018-05-23
| | | | | | | | | | | | | Reduces code size by: bare-arm: +0 minimal x86: +0 unix x64: -368 unix nanbox: -248 stm32: -128 cc3200: -48 esp8266: -184 esp32: -40
* py/emitnative: Implement floor-division and modulo for viper emitter.Damien George2017-10-11
|
* all: Remove inclusion of internal py header files.Damien George2017-10-04
| | | | | | | | | | | | | | | | Header files that are considered internal to the py core and should not normally be included directly are: py/nlr.h - internal nlr configuration and declarations py/bc0.h - contains bytecode macro definitions py/runtime0.h - contains basic runtime enums Instead, the top-level header files to include are one of: py/obj.h - includes runtime0.h and defines everything to use the mp_obj_t type py/runtime.h - includes mpstate.h and hence nlr.h, obj.h, runtime0.h, and defines everything to use the general runtime support functions Additional, specific headers (eg py/objlist.h) can be included if needed.
* py: Add verbose debug compile-time flag MICROPY_DEBUG_VERBOSE.Stefan Naumann2017-08-15
| | | | It enables all the DEBUG_printf outputs in the py/ source code.
* all: Use the name MicroPython consistently in commentsAlexander Steffen2017-07-31
| | | | | There were several different spellings of MicroPython present in comments, when there should be only one.
* 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: Optimise storage of iterator so it takes only 4 slots on Py stack.Damien George2017-02-16
|
* py/runtime: Convert mp_uint_t to size_t where appropriate.Damien George2017-02-16
|
* 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/viper: Allow casting of Python integers to viper pointers.Damien George2016-02-09
| | | | | | | | | This allows you to pass a number (being an address) to a viper function that expects a pointer, and also allows casting of integers to pointers within viper functions. This was actually the original behaviour, but it regressed due to native type identifiers being promoted to 4 bits in width.
* py: Extend native type-sig to use 4 bits, so uint is separate to ptr.Damien George2016-02-02
| | | | | | | Before this patch, the native types for uint and ptr/ptr8/ptr16/ptr32 all overlapped and it was possible to make a mistake in casting. Now, these types are all separate and any coding mistakes will be raised as runtime errors.
* 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/viper: Truncate viper integer args so they can be up to 32-bit.Damien George2016-01-07
|
* py: Rename MP_BOOL() to mp_obj_new_bool() for consistency in naming.Paul Sokolovsky2015-10-11
|
* py: Remove mp_load_const_bytes and instead load precreated bytes object.Damien George2015-06-25
| | | | | | | | | | | | | | | | Previous to this patch each time a bytes object was referenced a new instance (with the same data) was created. With this patch a single bytes object is created in the compiler and is loaded directly at execute time as a true constant (similar to loading bignum and float objects). This saves on allocating RAM and means that bytes objects can now be used when the memory manager is locked (eg in interrupts). The MP_BC_LOAD_CONST_BYTES bytecode was removed as part of this. Generated bytecode is slightly larger due to storing a pointer to the bytes object instead of the qstr identifier. Code size is reduced by about 60 bytes on Thumb2 architectures.
* py: Remove mp_load_const_str and replace uses with inlined version.Damien George2015-06-25
|
* py: Implement full func arg passing for native emitter.Damien George2015-04-07
| | | | | | | | | | | This patch gets full function argument passing working with native emitter. Includes named args, keyword args, default args, var args and var keyword args. Fully Python compliant. It reuses the bytecode mp_setup_code_state function to do all the hard work. This function is slightly adjusted to accommodate native calls, and the native emitter is forced a bit to emit similar prelude and code-info as bytecode.
* py: Implement calling functions with *args in native emitter.Damien George2015-04-06
|