Age | Commit message (Collapse) | Author |
|
|
|
According to EEP-43 for maps, a 'badmap' exception should be
generated when an attempt is made to update non-map term such as:
<<>>#{a=>42}
That was not implemented in the OTP 17.
José Valim suggested that we should take the opportunity to
improve the errors coming from map operations:
http://erlang.org/pipermail/erlang-questions/2015-February/083588.html
This commit implement better errors from map operations similar
to his suggestion.
When a map update operation (Map#{...}) or a BIF that expects a map
is given a non-map term, the exception will be:
{badmap,Term}
This kind of exception is similar to the {badfun,Term} exception
from operations that expect a fun.
When a map operation requires a key that is not present in a map,
the following exception will be raised:
{badkey,Key}
José Valim suggested that the exception should be
{badkey,Key,Map}. We decided not to do that because the map
could potentially be huge and cause problems if the error
propagated through links to other processes.
For BIFs, it could be argued that the exceptions could be simply
'badmap' and 'badkey', because the bad map and bad key can be found in
the argument list for the BIF in the stack backtrace. However, for the
map update operation (Map#{...}), the bad map or bad key will not be
included in the stack backtrace, so that information must be included
in the exception reason itself. For consistency, the BIFs should raise
the same exceptions as update operation.
If more than one key is missing, it is undefined which of
keys that will be reported in the {badkey,Key} exception.
|
|
For consistency with other data types, add the is_not_map() macro.
|
|
|
|
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.
|
|
It is no longer necessary to sort the keys, since the loader
does the sorting.
|
|
The BEAM loader will now sort keys for maps during loading, so
beam_validator should not require the keys to be ordered any order.
However, we must still ensure that literals keys are unique (which
was implicitly guaranteed by the strict ordering requirement).
|
|
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 has_map_fields instruction was not tested at all by
erts/map_SUITE.erl
|
|
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.
|
|
To be sure that the compiler and BEAM virtual machine correctly
handles literals maps, we must test it.
|
|
Create a clone of map_SUITE named map_no_opt_SUITE to ensure that
the loader can cope with unoptimized map instructions.
|
|
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)
|
|
|
|
Conflicts:
OTP_VERSION
|
|
|
|
|
|
* ia/ssh/packet_size0/OTP-12645:
ssh: Reset upgrade instructions to default
ssh: Change version (vsn.mk)
ssh: Option minimal_remote_max_packet_size and test cases
ssh: fix loop bug for zero maximum_packet_size.
ssh: Add ssh_info:print/1 to write onto a file descriptor
ssh: Add {active, false} to ssh listen socket
ssh: Change send_buf implementation from list to queue
ssh: Remove error report
|
|
* bjorn/stdlib/cuddle-with-tests:
Eliminate deprecated now/0 used as timestamp
Eliminate use of now/0 for creating a unique filename
Eliminate use of deprecated now/0 for measuring time
Eliminate use of deprecated now/0 for random number generation
Speed up timer_simple_SUITE:timer_perf/1
Speed up timer_SUITE
Optimize gen_server_SUITE:hibernate/1
Optimize gen_event_SUITE:hibernate/1
Optimize gen_fsm_SUITE:hibernate/1
Optimize unicode_SUITE:ex_binaries_errors* test cases
Optimize unicode_SUITE:binaries_errors/1
binary_module_SUITE: Remove unnecessary calls to the binref module
Optimize binary_module:random_ref_comp/1
Optimize io_proto_SUITE:unicode_options_gen/1
|
|
Rewrite the code to measure and print elapsed time instead of just
printing timestamps for the start and stop of each operation.
|
|
Use erlang:unique_integer/1 instead.
|
|
Use erlang:monotonic_time/1 instead of now/0.
|
|
Use erlang:timestamp/0 instead now/0 when seeding the random
number generator.
|
|
In big_test/1, there is 9 seconds sleep before spawning any timers.
Why? Before the sleep nrev processes are started, but they are likely
to finish running before the 9 seconds have elapsed.
Since I see no reason at all for the sleep, I will remove it.
|
|
The single test case in timer_SUITE is annoyingly slow. On average,
its running time is about 4 minutes (estimated by a
back-of-the-envelope calculation).
Scale down the delay times in the main loop and the length of timers
started. The running average time should now be around 80 seconds.
|
|
The running time for gen_server_SUITE:hibernate/1 is about 12 seconds
because of 1000 ms sleeps in the test case. Introduce a helper
function to avoid sleeping more than necessary.
While we are it, also remove all ?line macros in the test case.
|
|
The running time for gen_event_SUITE:hibernate/1 is about 20 seconds
because of 1000 ms sleeps in the test case. Introduce helper
functions to avoid sleeping more than necessary.
While we are it, also remove all ?line macros in the test case.
|
|
The running time for gen_fsm_SUITE:hibernate/1 is almost 30 seconds
because of 1000 ms sleeps in the test case. Introduce helper
functions to avoid sleeping more than necessary.
While we are it, also remove all ?line macros in the test case.
|
|
Refactor the code so that the error test cases for utf16 can
share the code for big and little endian. Do the same for utf32.
The major optimization is the observation that the following code:
byte_size(unicode:characters_to_binary(List, unicode, {utf16,big})
can be replaced with:
2*length(List)
which is much faster. (That optimization is not safe in general,
but for the lists used in the error tests cases, it is.)
|
|
unicode_SUITE:binaries_errors/1 is the slowest test case in
unicode_SUITE. Its running time is about 50 seconds on my computer.
Break apart unicode_SUITE:binaries_errors/1 into several test cases
that can run in parallel.
|
|
The compile_pattern/1 function in the binref module is a dummy
function. Therefore, calling binref:match/2 once with the plain
pattern and once with a "pre-compiled" pattern will take twice as
long, but will not help us find more errors.
I shaved off one fourth of the running time for random_ref_comp/1
by eliminating the unnecessary calls to the binref module.
|
|
* 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
|
|
|
|
Repeated keys will shrink map to a flatmap if the number of pairs drops below the limit.
|
|
* ia/ssl/improve_docs:
ssl: Document enhancements
ssl: Align with alphabetical order
ssl: Align with editorial changes
ssl: Correct merge error
ssl: Add links
ssl: Correct typos
ssl: Correct XML-tag
ssl: Technically clarify description
ssl: Editorial updates
|
|
|
|
|
|
|
|
|
|
|