summaryrefslogtreecommitdiff
path: root/py/runtime.c
AgeCommit message (Collapse)Author
2023-09-14py/runtime: Add helpers to call a general function on nlr jump callback.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2023-07-24py/runtime: Always initialise sched_state in mp_init.Damien George
When MICROPY_SCHEDULER_STATIC_NODES is enabled, the logic is unchanged. When MICROPY_SCHEDULER_STATIC_NODES is disable, sched_state is now always initialised to MP_SCHED_IDLE when calling mp_init(). For example, the use of mp_sched_vm_abort(), if it aborts a running scheduled function, can lead to the scheduler starting off in a locked state when the runtime is restarted, and then it stays locked. This commit fixes that case by resetting sched_state. Signed-off-by: Damien George <damien@micropython.org>
2023-06-08py/modsys: Allow sys.path to be assigned to.Jim Mussared
Previously sys.path could be modified by append/pop or slice assignment. This allows `sys.path = [...]`, which can be simpler in many cases, but also improves CPython compatibility. It also allows sys.path to be set to a tuple which means that you can clear sys.path (e.g. temporarily) with no allocations. This also makes sys.path (and sys.argv for consistency) able to be disabled via mpconfig. The unix port (and upytesthelper) require them, so they explicitly verify that they're enabled. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-02py: Use nlr jump callbacks to optimise compile/execute functions.Damien George
The changed functions now use less stack, and don't have any issues with local variables needing to be declared volatile. Testing on a PYBv1.0, imports (of .py, .mpy and frozen code) now use 64 less bytes of C stack per import depth. Signed-off-by: Damien George <damien@micropython.org>
2023-06-01py/builtinimport: Optimise sub-package loading.Jim Mussared
This makes it so that sub-packages are resolved relative to their parent's `__path__`, rather than re-resolving each parent's filesystem path. The previous behavior was that `import foo.bar` would first re-search `sys.path` for `foo`, then use the resulting path to find `bar`. For already-loaded and u-prefixed modules, because we no longer need to build the path from level to level, we no longer unnecessarily search the filesystem. This should improve startup time. Explicitly makes the resolving process clear: - Loaded modules are returned immediately without touching the filesystem. - Exact-match of builtins are also returned immediately. - Then the filesystem search happens. - If that fails, then the weak-link handling is applied. This maintains the existing behavior: if a user writes `import time` they will get time.py if it exits, otherwise the built-in utime. Whereas `import utime` will always return the built-in. This also fixes a regression from a7fa18c203a241f670f12ab507aa8b349fcd45a1 where we search the filesystem for built-ins. It is now only possible to override u-prefixed builtins. This will remove a lot of filesystem stats at startup, as micropython-specific modules (e.g. `pyb`) will no longer attempt to look at the filesystem. Added several improvements to the comments and some minor renaming and refactoring to make it clearer how the import mechanism works. Overall code size diff is +56 bytes on STM32. This work was funded through GitHub Sponsors. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-06-01py: Change MP_UNARY_OP_INT to MP_UNARY_OP_INT_MAYBE.Damien George
To be consistent with MP_UNARY_OP_INT_FLOAT and MP_UNARY_OP_INT_COMPLEX, and allow int() to first check if a type supports __int__ before trying other things (as per CPython). Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/runtime: If inplace binop fails then try corresponding normal binop.Damien George
The code that handles inplace-operator to normal-binary-operator fallback is moved in this commit from py/objtype.c to py/runtime.c, making it apply to all types, not just user classes. Signed-off-by: Damien George <damien@micropython.org>
2023-05-19py/obj: Remove mp_generic_unary_op().David Lechner
Since converting to variable sized slots in mp_obj_type_t, we can now reduce the code size a bit by removing mp_generic_unary_op() and the corresponding slots where it is used. Instead we just implement the generic `__hash__` operation in the runtime. Signed-off-by: David Lechner <david@pybricks.com>
2023-04-27all: Fix spelling mistakes based on codespell check.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2022-09-19py/runtime: Add mp_raise_OSError_with_filename helper function.Damien George
Useful when more detail is needed for an OSError associated with a file. Signed-off-by: Damien George <damien@micropython.org>
2022-09-19py/obj: Convert make_new into a mp_obj_type_t slot.Jim Mussared
Instead of being an explicit field, it's now a slot like all the other methods. This is a marginal code size improvement because most types have a make_new (100/138 on PYBV11), however it improves consistency in how types are declared, removing the special case for make_new. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19py/obj: Merge getiter and iternext mp_obj_type_t slots.Jim Mussared
The goal here is to remove a slot (making way to turn make_new into a slot) as well as reduce code size by the ~40 references to mp_identity_getiter and mp_stream_unbuffered_iter. This introduces two new type flags: - MP_TYPE_FLAG_ITER_IS_ITERNEXT: This means that the "iter" slot in the type is "iternext", and should use the identity getiter. - MP_TYPE_FLAG_ITER_IS_CUSTOM: This means that the "iter" slot is a pointer to a mp_getiter_iternext_custom_t instance, which then defines both getiter and iternext. And a third flag that is the OR of both, MP_TYPE_FLAG_ITER_IS_STREAM: This means that the type should use the identity getiter, and mp_stream_unbuffered_iter as iternext. Finally, MP_TYPE_FLAG_ITER_IS_GETITER is defined as a no-op flag to give the default case where "iter" is "getiter". Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19py/obj: Add accessors for type slots and use everywhere.Jim Mussared
This is a no-op, but sets the stage for changing the mp_obj_type_t representation. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-09-19all: Make all mp_obj_type_t defs use MP_DEFINE_CONST_OBJ_TYPE.Jim Mussared
In preparation for upcoming rework of mp_obj_type_t layout. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-08-06py/runtime: Fix crash in star arg unpacking.David Lechner
The reallocation trigger for unpacking star args with unknown length did not take into account the number of fixed args remaining. So it was possible that the unpacked iterators could take up exactly the memory allocated then nothing would be left for fixed args after the star args. This causes a segfault crash. This is fixed by taking into account the remaining number of fixed args in the check to decide whether to realloc yet or not. Signed-off-by: David Lechner <david@pybricks.com>
2022-07-25py/obj: Add support for __float__ and __complex__ functions.Andrew Leech
2022-06-02all: Remove third argument to MP_REGISTER_MODULE.Damien George
It's no longer needed because this macro is now processed after preprocessing the source code via cpp (in the qstr extraction stage), which means unused MP_REGISTER_MODULE's are filtered out by the preprocessor. Signed-off-by: Damien George <damien@micropython.org>
2022-05-18py: Make builtin modules use MP_REGISTER_MODULE.Jim Mussared
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-05-03all: Use mp_obj_malloc everywhere it's applicable.Jim Mussared
This replaces occurences of foo_t *foo = m_new_obj(foo_t); foo->base.type = &foo_type; with foo_t *foo = mp_obj_malloc(foo_t, &foo_type); Excludes any places where base is a sub-field or when new0/memset is used. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2022-04-14py/scheduler: Add support for scheduling static C-based callbacks.Damien George
If MICROPY_SCHEDULER_STATIC_NODES is enabled then C code can declare a static mp_sched_node_t and schedule a callback using mp_sched_schedule_node(). In contrast to using mp_sched_schedule(), the node version will have at most one pending callback outstanding, and will always be able to schedule if there is nothing already scheduled on this node. This guarantees that the the callback will be called exactly once after it is scheduled. Signed-off-by: Damien George <damien@micropython.org>
2022-04-01py/runtime: Remove unnecessary check for kw_value == MP_OBJ_NULL.Damien George
The values are always real objects, only the key can be MP_OBJ_NULL to indicate a **kwargs entry. Signed-off-by: Damien George <damien@micropython.org>
2022-04-01py: Fix compiling and decoding of *args at large arg positions.Damien George
There were two issues with the existing code: 1. "1 << i" is computed as a 32-bit number so would overflow when executed on 64-bit machines (when mp_uint_t is 64-bit). This meant that *args beyond 32 positions would not be handled correctly. 2. star_args must fit as a positive small int so that it is encoded correctly in the emitted code. MP_SMALL_INT_BITS is too big because it overflows a small int by 1 bit. MP_SMALL_INT_BITS - 1 does not work because it produces a signed small int which is then sign extended when extracted (even by mp_obj_get_int_truncated), and this sign extension means that any position arg after *args is also treated as a star-arg. So the maximum bit position is MP_SMALL_INT_BITS - 2. This means that MP_OBJ_SMALL_INT_VALUE() can be used instead of mp_obj_get_int_truncated() to get the value of star_args. These issues are fixed by this commit, and a test added. Signed-off-by: Damien George <damien@micropython.org>
2022-03-31py/runtime: Use size_t/ssize_t instead of uint/int.David Lechner
This replaces instances of uint with size_t and int with ssize_t in the mp_call_prepare_args_n_kw_var() function since all of the variables are used as array offsets. Also sort headers while we are touching this. Signed-off-by: David Lechner <david@pybricks.com>
2022-03-31py/runtime: Drop new_alloc < 4 check.David Lechner
To reach this check, n_kw has to be >= 1 and therefore args2_alloc has to be >= 2. Therefore new_alloc will always be >= 4. So this check will never be true and can be removed. Signed-off-by: David Lechner <david@pybricks.com>
2022-03-31py/runtime: Do not overallocate when len is known.David Lechner
This fixes overallocating an extra mp_obj_t when the length of *args and **args is known. Previously we were allocating 1 mp_obj_t for each n_args and n_kw plus the length of each *arg and **arg (if they are known). Since n_args includes *args and n_kw includes **args, this was allocating an extra mp_obj_t in addition to the length of these args when unpacked. To fix this, we just subtract 1 from the length to account for the 1 already implicitly allocated by n_args and n_kw. Signed-off-by: David Lechner <david@pybricks.com>
2022-03-31py/runtime: Allow multiple *args in a function call.David Lechner
This is a partial implementation of PEP 448 to allow unpacking multiple star args in a function or method call. This is implemented by changing the emitted bytecodes so that both positional args and star args are stored as positional args. A bitmap is added to indicate if an argument at a given position is a positional argument or a star arg. In the generated code, this new bitmap takes the place of the old star arg. It is stored as a small int, so this means only the first N arguments can be star args where N is the number of bits in a small int. The runtime is modified to interpret this new bytecode format while still trying to perform as few memory reallocations as possible. Signed-off-by: David Lechner <david@pybricks.com>
2022-03-31py/runtime: Allow multiple **args in a function call.David Lechner
This is a partial implementation of PEP 448 to allow multiple ** unpackings when calling a function or method. The compiler is modified to encode the argument as a None: obj key-value pair (similar to how regular keyword arguments are encoded as str: obj pairs). The extra object that was pushed on the stack to hold a single ** unpacking object is no longer used and is removed. The runtime is modified to decode this new format. Signed-off-by: David Lechner <david@pybricks.com>
2022-03-10py/modsys: Add optional mutable attributes sys.ps1/ps2 and use them.Damien George
This allows customising the REPL prompt strings. Signed-off-by: Damien George <damien@micropython.org>
2022-03-10py/modsys: Add optional sys.tracebacklimit attribute.Damien George
With behaviour as per CPython. Signed-off-by: Damien George <damien@micropython.org>
2021-12-29ports: Move '.frozen' to second entry in sys.path.Damien George
In commit 86ce4426079b1b368881c22f46d80045e2f720b0 the '.frozen' entry was added at the start of sys.path, to allow control over when frozen modules are searched during import, and retain existing behaviour whereby frozen was searched before the filesystem. But Python semantics of sys.path require sys.path[0] to be the directory of the currently executing script, or ''. This commit moves the '.frozen' entry to second place in sys.path, so sys.path[0] retains its correct value (described above). Signed-off-by: Damien George <damien@micropython.org>
2021-12-18py/runtime: Allow initialising sys.path/argv with defaults.Damien George
If MICROPY_PY_SYS_PATH_ARGV_DEFAULTS is enabled (which it is by default) then sys.path and sys.argv will be initialised and populated with default values. This keeps all bare-metal ports aligned. Signed-off-by: Damien George <damien@micropython.org>
2021-11-22py/runtime: Allow types to use both .attr and .locals_dict.Laurens Valk
Make it possible to proceed to a regular lookup in locals_dict if the custom type->attr fails. This allows type->attr to extend rather than completely replace the lookup in locals_dict. This is useful for custom builtin classes that have mostly regular methods but just a few special attributes/properties. This way, type->attr needs to deal with the special cases only and the default lookup will be used for generic methods. Signed-off-by: Laurens Valk <laurens@pybricks.com>
2021-10-21py/runtime: Fix crash when exc __new__ doesn't return an exc instance.Mike Wadsten
See CPython bug https://bugs.python.org/issue39091 for more details.
2021-10-15py: Add wrapper macros so hot VM functions can go in fast code location.Damien George
For example, on esp32 they can go in iRAM to improve performance. Signed-off-by: Damien George <damien@micropython.org>
2021-09-16py/vm: Add a fast path for LOAD_ATTR on instance types.Jim Mussared
When the LOAD_ATTR opcode is executed there are quite a few different cases that have to be handled, but the common case is accessing a member on an instance type. Typically, built-in types provide methods which is why this is common. Fortunately, for this specific case, if the member is found in the member map then there's no further processing. This optimisation does a relatively cheap check (type is instance) and then forwards directly to the member map lookup, falling back to the regular path if necessary. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2021-07-23py/runtime: Fix bool unary op for subclasses of native types.Jim Mussared
Previously a subclass of a type that didn't implement unary_op, or didn't handle MP_UNARY_OP_BOOL, would raise TypeError on bool conversion. Fixes #5677.
2021-07-15py: Introduce and use mp_raise_type_arg helper.Damien George
To reduce code size. Signed-off-by: Damien George <damien@micropython.org>
2021-07-15py: Support single argument to optimised MP_OBJ_STOP_ITERATION.Damien George
The MP_OBJ_STOP_ITERATION optimisation is a shortcut for creating a StopIteration() exception object, and means that heap memory does not need to be allocated for the exception (in cases where it can be used). This commit allows this optimised object to take an optional argument (before, it could only have no argument). The commit also adds some new tests to cover corner cases with StopIteration and generators that previously did not work. Signed-off-by: Damien George <damien@micropython.org>
2021-07-15py/vm: Simplify handling of MP_OBJ_STOP_ITERATION in yield-from opcode.Damien George
Signed-off-by: Damien George <damien@micropython.org>
2021-06-24all: Fix signed shifts and NULL access errors from -fsanitize=undefined.Jeff Epler
Fixes the following (the line numbers match commit 0e87459e2bfd07): ../../extmod/crypto-algorithms/sha256.c:49:19: runtime error: left shif... ../../extmod/moduasyncio.c:106:35: runtime error: member access within ... ../../py/binary.c:210:13: runtime error: left shift of negative value -... ../../py/mpz.c:744:16: runtime error: negation of -9223372036854775808 ... ../../py/objint.c:109:22: runtime error: left shift of 1 by 31 places c... ../../py/objint_mpz.c:374:9: runtime error: left shift of 4611686018427... ../../py/objint_mpz.c:374:9: runtime error: left shift of negative valu... ../../py/parsenum.c:106:14: runtime error: left shift of 46116860184273... ../../py/runtime.c:395:33: runtime error: left shift of negative value ... ../../py/showbc.c:177:28: runtime error: left shift of negative value -... ../../py/vm.c:321:36: runtime error: left shift of negative value -1``` Testing was done on an amd64 Debian Buster system using gcc-8.3 and these settings: CFLAGS += -g3 -Og -fsanitize=undefined LDFLAGS += -fsanitize=undefined The introduced TASK_PAIRHEAP macro's conditional (x ? &x->i : NULL) assembles (under amd64 gcc 8.3 -Os) to the same as &x->i, since i is the initial field of the struct. However, for the purposes of undefined behavior analysis the conditional is needed. Signed-off-by: Jeff Epler <jepler@gmail.com>
2021-06-19py/mpstate: Make exceptions thread-local.David Lechner
This moves mp_pending_exception from mp_state_vm_t to mp_state_thread_t. This allows exceptions to be scheduled on a specific thread. Signed-off-by: David Lechner <david@pybricks.com>
2021-04-30py/runtime: Remove commented-out code from mp_deinit().Damien George
These commented-out lines of code have been unused for a long time, so remove them to avoid confusion as to why they are there. mp_obj_dict_free() never existed, this line was converted from mp_map_deinit() and commented out as soon as it was added. The call to mp_map_deinit(mp_loaded_modules_map) was commented in 1a1d11fa32ba043d22995d28cbc039cfa5f3cc46. Fixes issue #3507. Signed-off-by: Damien George <damien@micropython.org>
2021-04-27py: Add option to compile without any error messages at all.Damien George
This introduces a new option, MICROPY_ERROR_REPORTING_NONE, which completely disables all error messages. To be used in cases where MicroPython needs to fit in very limited systems. Signed-off-by: Damien George <damien@micropython.org>
2021-04-12py/runtime: Make sys.modules preallocate to a configurable size.matejcik
This allows configuring the pre-allocated size of sys.modules dict, in order to prevent unwanted reallocations at run-time (3 sys-modules is really not quite enough for a larger project).
2021-02-04py: Rename BITS_PER_BYTE to MP_BITS_PER_BYTE.Damien George
To give this macro a standard MP_ prefix. Signed-off-by: Damien George <damien@micropython.org>
2021-02-04py: Remove BITS_PER_WORD definition.Damien George
It's only used in one location, to test if << or >> will overflow when shifting mp_uint_t. For such a test it's clearer to use sizeof(lhs_val), which will be valid even if the type of lhs_val changes. Signed-off-by: Damien George <damien@micropython.org>
2020-08-22py/runtime: Fix builtin compile() in "single" mode so it prints exprs.Damien George
As per CPython behaviour, compile(stmt, "file", "single") should create code which prints to stdout (via __repl_print__) the results of any expressions in stmt. Signed-off-by: Damien George <damien@micropython.org>
2020-08-02py/persistentcode: Maintain root ptr list of imported native .mpy code.Damien George
On ports where normal heap memory can contain executable code (eg ARM-based ports such as stm32), native code loaded from an .mpy file may be reclaimed by the GC because there's no reference to the very start of the native machine code block that is reachable from root pointers (only pointers to internal parts of the machine code block are reachable, but that doesn't help the GC find the memory). This commit fixes this issue by maintaining an explicit list of root pointers pointing to native code that is loaded from an .mpy file. This is not needed for all ports so is selectable by the new configuration option MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE. It's enabled by default if a port does not specify any special functions to allocate or commit executable memory. A test is included to test that native code loaded from an .mpy file does not get reclaimed by the GC. Fixes #6045. Signed-off-by: Damien George <damien@micropython.org>
2020-06-30py: Rework mp_convert_member_lookup to properly handle built-ins.Damien George
This commit fixes lookups of class members to make it so that built-in functions that are used as methods/functions of a class work correctly. The mp_convert_member_lookup() function is pretty much completely changed by this commit, but for the most part it's just reorganised and the indenting changed. The functional changes are: - staticmethod and classmethod checks moved to later in the if-logic, because they are less common and so should be checked after the more common cases. - The explicit mp_obj_is_type(member, &mp_type_type) check is removed because it's now subsumed by other, more general tests in this function. - MP_TYPE_FLAG_BINDS_SELF and MP_TYPE_FLAG_BUILTIN_FUN type flags added to make the checks in this function much simpler (now they just test this bit in type->flags). - An extra check is made for mp_obj_is_instance_type(type) to fix lookup of built-in functions. Fixes #1326 and #6198. Signed-off-by: Damien George <damien@micropython.org>
2020-04-23all: Format code to add space after C++-style comment start.stijn
Note: the uncrustify configuration is explicitly set to 'add' instead of 'force' in order not to alter the comments which use extra spaces after // as a means of indenting text for clarity.