Commit Graph

63 Commits

Author SHA1 Message Date
Philip Peitsch edc92d18db py/map: Clear value when re-using slot with ordered dictionaries.
To adhere to the contract of mp_map_lookup, namely:

    MP_MAP_LOOKUP_ADD_IF_NOT_FOUND behaviour:
    - returns slot, with key non-null and value=MP_OBJ_NULL if it was added
2023-01-13 14:21:32 +11:00
Yonatan Goldschmidt 2a6ba47110 py/obj: Add static safety checks to mp_obj_is_type().
Commit d96cfd13e3 introduced a regression by breaking existing
users of mp_obj_is_type(.., &mp_obj_bool).  This function (and associated
helpers like mp_obj_is_int()) have some specific nuances, and mistakes like
this one can happen again.

This commit adds mp_obj_is_exact_type() which behaves like the the old
mp_obj_is_type().  The new mp_obj_is_type() has the same prototype but it
attempts to statically assert that it's not called with types which should
be checked using mp_obj_is_type().  If called with any of these types: int,
str, bool, NoneType - it will cause a compilation error.  Additional
checked types (e.g function types) can be added in the future.

Existing users of mp_obj_is_type() with the now "invalid" types, were
translated to use mp_obj_is_exact_type().

The use of MP_STATIC_ASSERT() is not bulletproof - usually GCC (and other
compilers) can't statically check conditions that are only known during
link-time (like variables' addresses comparison).  However, in this case,
GCC is able to statically detect these conditions, probably because it's
the exact same object - `&mp_type_int == &mp_type_int` is detected.
Misuses of this function with runtime-chosen types (e.g:
`mp_obj_type_t *x = ...; mp_obj_is_type(..., x);` won't be detected.  MSC
is unable to detect this, so we use MP_STATIC_ASSERT_NOT_MSC().

Compiling with this commit and without the fix for d96cfd13e3 shows
that it detects the problem.

Signed-off-by: Yonatan Goldschmidt <yon.goldschmidt@gmail.com>
2022-07-18 11:17:46 +10:00
Damien George 8412568e7b py: Add wrapper macros so hot VM functions can go in fast code location.
For example, on esp32 they can go in iRAM to improve performance.

Signed-off-by: Damien George <damien@micropython.org>
2021-10-15 23:31:19 +11:00
Jim Mussared 11ef8f22fe py/map: Add an optional cache of (map+index) to speed up map lookups.
The existing inline bytecode caching optimisation, selected by
MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE, reserves an extra byte in the
bytecode after certain opcodes, which at runtime stores a map index of the
likely location of this field when looking up the qstr.  This scheme is
incompatible with bytecode-in-ROM, and doesn't work with native generated
code.  It also stores bytecode in .mpy files which is of a different format
to when the feature is disabled, making generation of .mpy files more
complex.

This commit provides an alternative optimisation via an approach that adds
a global cache for map offsets, then all mp_map_lookup operations use it.
It's less precise than bytecode caching, but allows the cache to be
independent and external to the bytecode that is executing.  It also works
for the native emitter and adds a similar performance boost on top of the
gain already provided by the native emitter.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2021-09-16 16:02:19 +10:00
Jim Mussared 880875bea1 py/objdict: Add mp_const_empty_dict_obj, use it for mp_const_empty_map. 2020-10-10 00:16:26 +11:00
Jim Mussared 57fce3bdb2 py/objdict: Fix popitem for ordered dicts.
The popitem method wasn't implemented for ordered dicts and would result in
an invalid state.

Fixes issue #5956.
2020-04-27 23:53:17 +10:00
Damien George 69661f3343 all: Reformat C and Python source code with tools/codeformat.py.
This is run with uncrustify 0.70.1, and black 19.10b0.
2020-02-28 10:33:03 +11:00
Damien George 054dd33eba py: Downcase MP_xxx_SLOT_IS_FILLED inline functions. 2019-02-12 14:54:51 +11:00
Damien George eee1e8841a py: Downcase all MP_OBJ_IS_xxx macros to make a more consistent C API.
These macros could in principle be (inline) functions so it makes sense to
have them lower case, to match the other C API functions.

The remaining macros that are upper case are:
- MP_OBJ_TO_PTR, MP_OBJ_FROM_PTR
- MP_OBJ_NEW_SMALL_INT, MP_OBJ_SMALL_INT_VALUE
- MP_OBJ_NEW_QSTR, MP_OBJ_QSTR_VALUE
- MP_OBJ_FUN_MAKE_SIG
- MP_DECLARE_CONST_xxx
- MP_DEFINE_CONST_xxx

These must remain macros because they are used when defining const data (at
least, MP_OBJ_NEW_SMALL_INT is so it makes sense to have
MP_OBJ_SMALL_INT_VALUE also a macro).

For those macros that have been made lower case, compatibility macros are
provided for the old names so that users do not need to change their code
immediately.
2019-02-12 14:54:51 +11:00
Damien George b630dfcc1d py: Fix compiling with debug enabled and make more use of DEBUG_printf.
DEBUG_printf and MICROPY_DEBUG_PRINTER is now used instead of normal
printf, and a fault is fixed in mp_obj_class_lookup with debugging enabled;
see issue #3999.  Debugging can now be enabled on all ports including when
nan-boxing is used.
2018-08-02 14:17:24 +10:00
Damien George 136cb7f27c py/map: Don't include ordered-dict mutating code when not needed. 2017-12-19 13:37:15 +11:00
Paul Sokolovsky a35d923cdf py/map: Allow to trace rehashing operations. 2017-12-09 17:32:16 +02:00
Damien George a3dc1b1957 all: Remove inclusion of internal py header files.
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.
2017-10-04 12:37:50 +11:00
Damien George 6c9fca2aa9 py/map: Remove unused new/free functions.
Maps are always allocated "statically" and (de)initialised via mp_map_init
and mp_map_deinit.
2017-08-31 16:46:13 +10:00
Damien George 0e420d48ee py/map: Replace always-false condition with assertion. 2017-08-31 16:45:02 +10:00
Alexander Steffen 55f33240f3 all: Use the name MicroPython consistently in comments
There were several different spellings of MicroPython present in comments,
when there should be only one.
2017-07-31 18:35:40 +10:00
Damien George 9275c18270 py/map: Fix bugs with deletion of elements from OrderedDict.
There were 2 bugs, now fixed by this patch:
- after deleting an element the len of the dict did not decrease by 1
- after deleting an element searching through the dict could lead to
  a seg fault due to there being an MP_OBJ_SENTINEL in the ordered array
2017-03-03 11:21:19 +11:00
Damien George af622eb2a6 py/map: Change mp_uint_t to size_t where appropriate.
The internal map/set functions now use size_t exclusively for computing
addresses.  size_t is enough to reach all of available memory when
computing addresses so is the right type to use.  In particular, for
nanbox builds it saves quite a bit of code size and RAM compared to the
original use of mp_uint_t (which is 64-bits on nanbox builds).
2017-02-08 11:00:15 +11:00
Damien George 3ff16ff52e py: Declare constant data as properly constant.
Otherwise some compilers (eg without optimisation) will put this read-only
data in RAM instead of ROM.
2016-05-20 12:46:20 +01:00
Damien George 00137b8c11 py/map: Change hash-table allocation policy to be less aggressive.
Small hash tables (eg those used in user class instances that only have a
few members) now only use the minimum amount of memory necessary to hold
the key/value pairs.  This can reduce performance for instances that have
many members (because then there are many reallocations/rehashings of the
table), but helps to conserve memory.

See issue #1760.
2016-04-15 16:24:46 +01:00
Stephen Kyle b475327ffa py/map: Prevent map resize failure from destroying map. 2016-04-01 16:36:00 +03:00
Damien George 6dde019d93 py/map: In map lookup, check for fixed map independent of ordered map.
It's possible to have a fixed map that is properly hashed (ie not
simply ordered).
2015-12-31 00:24:33 +00:00
Damien George bbe8d51bd9 py/map: Add fast-path for hashing of map index when it is a qstr.
Map indicies are most commonly a qstr, and adding a fast-path for hashing
of a qstr increases overall performance of the runtime.

On pyboard there is a 4% improvement in the pystone benchmark for a cost
of 20 bytes of code size.  It's about a 2% improvement on unix.
2015-12-26 21:15:47 +00:00
Damien George 83229d3ffe py: Use MP_OBJ_NULL instead of NULL when appropriate. 2015-11-20 14:09:20 +00:00
Damien George 593faf14c4 py/map: Store key/value in earliest possible slot in hash table.
This change makes the code behave how it was supposed to work when first
written.  The avail_slot variable is set to the first free slot when
looking for a key (which would come from deleting an entry).  So it's
more efficient (for subsequent lookups) to insert a new key into such a
slot, rather than the very last slot that was searched.
2015-11-19 01:27:28 +00:00
Damien George c2a4e4effc py: Convert hash API to use MP_UNARY_OP_HASH instead of ad-hoc function.
Hashing is now done using mp_unary_op function with MP_UNARY_OP_HASH as
the operator argument.  Hashing for int, str and bytes still go via
fast-path in mp_unary_op since they are the most common objects which
need to be hashed.

This lead to quite a bit of code cleanup, and should be more efficient
if anything.  It saves 176 bytes code space on Thumb2, and 360 bytes on
x86.

The only loss is that the error message "unhashable type" is now the
more generic "unsupported type for __hash__".
2015-05-12 22:46:02 +01:00
Damien George 2801e6fad8 py: Some trivial cosmetic changes, for code style consistency. 2015-04-04 15:53:11 +01:00
Damien George d1cee02783 py: Clarify API for map/set lookup when removing&adding at once.
Addresses issue #1160.
2015-03-20 17:41:37 +00:00
Paul Sokolovsky 0ef01d0a75 py: Implement core of OrderedDict type.
Given that there's already support for "fixed table" maps, which are
essentially ordered maps, the implementation of OrderedDict just extends
"fixed table" maps by adding an "is ordered" flag and add/remove
operations, and reuses 95% of objdict code, just making methods tolerant
to both dict and OrderedDict.

Some things are missing so far, like CPython-compatible repr and comparison.

OrderedDict is Disabled by default; enabled on unix and stmhal ports.
2015-03-20 17:26:10 +00:00
Damien George 963a5a3e82 py, unix: Allow to compile with -Wsign-compare.
See issue #699.
2015-01-16 17:47:07 +00:00
Damien George 51dfcb4bb7 py: Move to guarded includes, everywhere in py/ core.
Addresses issue #1022.
2015-01-01 20:32:09 +00:00
Damien George e37dcaafb4 py: Allow to properly disable builtin "set" object.
This patch makes MICROPY_PY_BUILTINS_SET compile-time option fully
disable the builtin set object (when set to 0).  This includes removing
set constructor/comprehension from the grammar, the compiler and the
emitters.  Now, enabling set costs 8168 bytes on unix x64, and 3576
bytes on stmhal.
2014-12-27 17:33:30 +00:00
Paul Sokolovsky e5dbe1e283 map: Add empty fixed map.
Useful when need to call kw-receiving functions  without any keywords
from C, etc.
2014-11-27 17:37:07 +00:00
Damien George 7860c2a68a py: Fix some macros defines; cleanup some includes. 2014-11-05 21:16:41 +00:00
Damien George 93965e726f py: Make map, dict, set use mp_int_t/mp_uint_t exclusively.
Part of code cleanup, towards resolving issue #50.
2014-08-30 13:23:35 +01:00
Damien George 40f3c02682 Rename machine_(u)int_t to mp_(u)int_t.
See discussion in issue #50.
2014-07-03 13:25:24 +01:00
Paul Sokolovsky 59c675a64c py: Include mpconfig.h before all other includes.
It defines types used by all other headers.

Fixes #691.
2014-06-21 22:43:22 +03:00
Damien George 04b9147e15 Add license header to (almost) all files.
Blanket wide to all .c and .h files.  Some files originating from ST are
difficult to deal with (license wise) so it was left out of those.

Also merged modpyb.h, modos.h, modstm.h and modtime.h in stmhal/.
2014-05-03 23:27:38 +01:00
Damien George 186e463a9e py: Fix bug in map lookup of interned string vs non-interned.
Had choice of either interning or forcing full equality comparison, and
chose latter.  See comments in mp_map_lookup.

Addresses issue #523.
2014-04-28 12:11:57 +01:00
Damien George 2bfd2dc770 py: Revert revert for allocation policy of set hash table. 2014-04-07 01:16:17 +01:00
Damien George c75427baaa py: Revert change to allocation policy for mp_set_t.
Seems that this fixes all set tests.
2014-04-07 00:54:04 +01:00
Paul Sokolovsky 5fedd0c3b7 py: Fix dict.copy() and low-level map/set allocation.
Two things: 1) set flags in copy properly; make mp_map_init() not be too
smart and do something with requested alloc size. Policy of using prime
numbers for alloc size is high-level policy which should be applied at
corresponding high levels. Low-level functions should just do what they're
asked to, because they don't have enough context to be smarter than that.
For example, munging with alloc size of course breaks dict copying (as
changing sizes requires rehashing).
2014-04-06 21:31:42 +03:00
Damien George d0e824387e py: Make mp_map_lookup not allocate memory on removal. 2014-04-05 23:33:12 +01:00
Damien George 8b0535e23f py: Change module globals from mp_map_t* to mp_obj_dict_t*.
Towards addressing issue #424.

Had a small increase to ROM usage (order 60 bytes).
2014-04-05 21:53:54 +01:00
Damien George 95004e5114 py: Fix delete operation on map/dict and set objects.
Hash table can now be completely full (ie now NULL entry) before a
resize is triggered.  Use sentinel value to indicate delete entry in the
table.
2014-04-05 17:17:19 +01:00
Paul Sokolovsky 4a088f4b61 map: When removing a key, don't NULL the entry, but mark as deleted.
When searching next time, such entry should be just skipped, not terminate
the search. It's known that marking techique is not efficient at the presense
of many removes, but namespace usage should not require many deletes, and
as for user dictionaries - well, open addressing map table with linear
rehashing and load factor of ~1 is not particularly efficient at all ;-).
TODO: May consider "shift other entries in cluster" approach as an
alternative.
2014-04-05 05:11:12 +03:00
Paul Sokolovsky e3f58c8380 map: Add mp_map_dump() (#ifdef'ed) to be handy when debugging maps. 2014-04-05 05:10:02 +03:00
Damien George df6567e634 Merge map.h into obj.h.
Pretty much everyone needs to include map.h, since it's such an integral
part of the Micro Python object implementation.  Thus, the definitions
are now in obj.h instead.  map.h is removed.
2014-03-30 13:54:02 +01:00
xbe efe3422394 py: Clean up includes.
Remove unnecessary includes. Add includes that improve portability.
2014-03-17 02:43:40 -07:00
Paul Sokolovsky 520e2f58a5 Replace global "static" -> "STATIC", to allow "analysis builds". Part 2. 2014-02-12 18:31:30 +02:00