Age | Commit message (Collapse) | Author |
|
|
|
See the previous commit for justification and use cases.
|
|
Let the loader pre-compute the hash value when a single, literal key
is matched as in:
#{<<"some_key">>:=V} = Map
In my measurements, this optimization resulted in a 30 percent
speedup for short binary keys.
Unfortunately, this optimizization makes no difference for small
maps with less than 32 keys, since the hash value is not used.
Still, there are the following use cases:
* A map used instead of a record with more than 32 entries. I have
seen some applications with huge records.
* Lookup in JSON dictionaries represented as maps.
The hash value will only be used when the map is a hash map
(currently, that means at least 32 entries).
|
|
In the i_get_map_element/4 instruction, for literal keys other than
atoms, the key would be put into x[0] instead of used directly in the
instruction. The reason is that the original implementation of maps
only supported atom keys.
|
|
In the update loop for big maps, the E variable is restored for
each turn of the loop. It only needs to be restored if a garbage
collection has been performed.
Also add a new test case that attempts to force several garbage
collections while updating a map, to help us find bugs with
incorrect restoration of the E variable after a garbage collection.
|
|
The map instructions require that the keys in the instructions
are sorted (for flatmaps). But that is an implementation detail
that should not exposed outside of the BEAM virtual machine.
Therefore, make the sorting of the keys the responsibility of
the loader and not the compiler.
Also note that the sort order for maps with numeric keys or keys
with numeric components has changed in OTP 18. That means that
code compiled for OTP 17 that operated on maps with map keys
might not work in OTP 18 without the sorting in the loader
(although it is unlikely to be an issue in practice).
|
|
The has_map_fields instruction is infrequently used. Thus there
is no need to have the fastest possible implementation; it is
better to have an implementation that reduces the code size in
the already big process_main() function.
We can transform has_map_fields to a get_map_elements instruction,
targeting the same unused x[0] register for all keys. That
instruction will only be marginally slower than existing
implementation.
|
|
The compiler will only emit is_map/1 instructions with literal
argument if optimization is turned off. Therefore, the only
reason for this commit is cleanliness.
|
|
The new_map instruction cannot fail, and thus needs no fail label.
|
|
A put_map_assoc instruction with an empty source map should be
converted to a simpler new_map instruction. The transformation
didn't happen because an empty source map is no longer represented
as a NIL term (as it was in the beginning before map literals
were implemented).
|
|
Using the exact operator (':=') is only allowed when an existing map
is being updated. Thus the following causes a compilation error:
#{k:=v}
Therefore there is no need to support the put_map_exact instruction
without a source map.
|
|
* egil/maps-test-coverage:
erts: Remove code that was commented out
erts: Cover maps:values/1 for large maps
erts: Test maps:from_list/1 shrinking
|
|
* egil/fix-maps-deep-colliding-merge:
erts: Fix deep colliding hash values in maps:from_list/1
|
|
* egil/fix-hash-float-zero/OTP-12641:
erts: Ensure hashing of zero is consistent
|
|
Erlang treats positive and negative zero as equal, meaning,
true = 0.0 =:= 0.0/-1
However, Erlangs hash functions: hash, phash and phash2 did not
reflect this behaviour. Meaning, the hash values produced by
the different hash functions would not be identical for positive
and negative zero.
This commit ensures that hash value of positive zero is always
produced regardless of the signedness of the zero float, i.e.
true = erlang:phash2(0.0) =:= erlang:phash2(0.0/-1)
|
|
|
|
* sverk/maps-bin2term-eqhash-bug/12585:
erts: Fix bug in map_from_list when keys clash in both value and hash
erts: Fix bug in binary_to_term for big maps with 32 bit hash-clash
|
|
* sverk/refactor-encode-size/OTP-12585:
erts: Optimize insert and delete for big maps
erts: Optimize == and /= for unequal big maps
erts: Refactor encode_size_struct_int
Conflicts:
erts/emulator/beam/erl_map.c
|
|
* sverk/ets-grow-faulty-assert/OTP-12647:
erts: Fix ets bug in debug VM
|
|
Symptom: ASSERT(segtab[seg_ix] == NULL) in alloc_seg() fails.
Remedy: Make sure we set segment pointer to NULL in free_seg()
even when we switch to smaller segtab.
|
|
* sverk/valgrind-broken_halt:
erts: Suppress valgrind for bif_SUITE:erlang_halt
|
|
Subtle bug in qsort callback. Cast from Sint to int does not retain sign.
|
|
binary_to_term threw badarg as the "reject_dupkey" case in
hashmap_from_unsored_array was always triggered when hash-clash was
found as the first round in the loop compared the key with itself.
|
|
Reported-by: Jesper Louis Andersen
|
|
* egil/fix-maps-tmp-heap:
erts: Test deep Maps updates
erts: Use halfword secure tmp heap
erts: Remove unused tmp heap in make_internal_hash
Conflicts:
erts/emulator/test/map_SUITE.erl
|
|
|
|
|
|
The wrong size was imprinted on maps with deep hash key collisions.
|
|
Do fast path without bit count for full internal nodes.
|
|
Bail out as soon as we find a diff between maps
if we are not interested in term order.
|
|
to handle the "start of list" case in one place and not seven.
Note that this commit reverts (47d6fd3ccf35) back to using WSTACK
and pushing raw pointers. We disable GC while yielding, so this should not
be a problem.
|
|
which does a deliberate deref of null pointer which is caught by
a SEGV signal handler to resume crash dumping.
|
|
* egil/fix-maps-new_map-instruction:
erts: Eliminate potential heap fragments after Map creation
|
|
* egil/fix-make_internal_hash-float:
erts: Add tests for internal_hash
erts: Fix make_internal_hash for 0.0 vs -0.0
|
|
|
|
The internal_hash should produce the same hash value for
identical terms, in this case 0.0 =:= -0.0.
|
|
Conflicts:
lib/stdlib/src/stdlib.appup.src
|
|
* sverk/large-list_to_integer-bug/OTP-12624:
erts: Fix bug in list_to_integer for very large strings
|
|
* dgud/erts/fix-driver-thread-name:
Fix thread name from driver api
|
|
* egil/fix-make_internal_hash:
erts: Fix missing case in make_internal_hash
|
|
* sverk/hamt-encode-size-bug/OTP-12585:
erts: Fix bug in term_to_binary size estimation for hamt
erts: Optimize term_to_binary size estimation
|
|
|
|
* rickard/time_api/OTP-11997:
Misc fixes
Conflicts:
erts/preloaded/ebin/erlang.beam
erts/preloaded/ebin/erts_internal.beam
|
|
|
|
* egil/maint/process_dictionary-initial-size/OTP-12535:
erts: Document option 'hpds'
erts: Enable command line argument for initial pd size
|
|
* egil/maps/refactor-tagscheme/OTP-12585:
erts: Refactor Map - use multiple values ESTACK_PUSHN
erts: GC needs the size even if the frag is not referenced
Revert "hipe: Handle separate hashmap tag correctly"
erts: Combine flat and hash maps under one unifying tag
|
|
|
|
for tuples and maps containing ascii strings (lists).
|
|
|
|
|