Age | Commit message (Collapse) | Author |
|
by adding a dynamic heap factory.
"binary_to_term" is now a hybrid solution with both
a call to decoded_size() to calculate needed heap space
AND possible dynamic allocation of more heap space
if needed for big maps.
The heap size returned from decoded_size() is guaranteed
to be sufficient for all term heap data except for hashmap
nodes. All hashmap nodes are created at the end of dec_term()
by invoking the heap factory interface that may allocate more
heap space on process heap or in fragments.
With this commit it is no longer guaranteed that a message
is confined to only one heap fragment.
|
|
Previously, the emulator would generate a whole string
with values and call the error_logger passing "~s~n".
This commit changes it to a format string containing ~p
with the respective values as arguments.
|
|
* rickard/timer-optimization/OTP-12650:
Optimized timer implementation
Reusable red-black tree implementation
Conflicts:
erts/emulator/beam/erl_bif_timer.c
|
|
|
|
* egil/opt-instructions/OTP-12690:
erts: Specialize minus and plus instruction
erts: Add move2 specialization for common move patterns
erts: Specialize rem instruction for common case
erts: Specialize band instruction for common case
erts: Batch loads and stores for move_window
erts: Fix loader increment from minus instruction
erts: Add move window instruction
erts: Add instruction move3 for xy and xx
erts: Specialize compare instructions
kernel: Add instruction_count helper to erts_debug
|
|
Seen on SSL application where substraction with x registers were prevalent:
* i_minus specialization on x registers
* i_plus specialization on x registers
|
|
* i_rem specialization on x registers
|
|
* i_band specialization on x registers and constants
|
|
May lessen load/store latency.
|
|
Move an entire region of x registers to the stack.
This reduces the dispatch pressure of move instructions.
Also introduce a move2 specialization for some common move patterns:
move r y | move x y -> move2 : As above, moving regions to the stack
move x r | move x y -> move2 : A seemingly common pattern
|
|
|
|
* i_is_lt for r, x registers and constants
* i_is_ge for x registers and constants
* i_is_exact_eq for r and x registers
|
|
* sverk/pr632/prevent-illegal-nif-terms/OTP-12655:
erts: Reject non-finite float terms in erl_drv_output_term
erts: Remove old docs about experimental NIF versions.
erts: Add enif_has_pending_exception
erts: Clearify erl_nif documentation about badarg exception
erts: Fix compile warning in enif_make_double
erts: Fix divide by zero compile error in nif_SUITE.c
erts: Fix isfinite for windows
Ensure NIF term creation disallows illegal values
|
|
* Assertion is only removed because we are in icount mode.
|
|
* bjorn/maps:
Document the new {badmap,Term} and {badkey,Key} exceptions
Raise more descriptive error messages for failed map operations
erl_term.h: Add is_not_map() macro
Tigthen code for the i_get_map_elements/3 instruction
Pre-compute hash values for the general get_map_elements instruction
Teach the loader to pre-compute the hash value for single-key lookups
Optimize use of i_get_map_element/4
beam_emu: Slightly optimize update_map_{assoc,exact}
v3_codegen: Don't sort map keys in map creation/update
beam_validator: No longer require strict literal term order
Sort maps keys in the loader
De-optimize the has_map_fields instructions
erts/map_SUITE.erl: Add a test case that tests has_map_fields
Fully evaluate is_map/1 for literals at load-time
map_SUITE: Add tests of is_map/1 with literal maps
Run a clone of map_SUITE without optimizations
Remove the fail label operand of the new_map instruction
Correct transformation of put_map_assoc to new_map
Remove support for put_map_exact without a source map
|
|
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.
|
|
|
|
|
|
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 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 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 new_map instruction cannot fail, and thus needs no fail label.
|
|
|
|
|
|
* egil/maps/hamt/OTP-12585: (113 commits)
erts: Fix bug in ESTACK and WSTACK
kernel: Add spec for erts_debug:map_info/1
mnesia: Update mnesia tests to reflect new ETS hash
erts: Ensure maps uses _rel functions in halfword
erts: Do not treat errors as fatal in erl_printf_term
erts: Update preloaded erts_internal.beam
erts: Add map decomposition wrappers
erts: Ensure halfword has correct temp-heap for maps
hipe: Handle separate hashmap tag correctly
erts: Fix map bug in dec_term for 32-bit debug VM
stdlib: Update qlc tests to reflect new ETS hash
stdlib: Remove obsolete hashmap references in io_lib
erts: Enhance maps ordering tests
hipe: Fix maps sort order testcase
erts: Remove unused variable in crashdump creation
erts: Fix typo in copy_struct for halfword emulator
erts: Restrict GCC intrinsics by compiler version
erts: Fix windows bug in hashmap_info
erts: Fix typo in make_hash2 for 32-bit arch
Fix beam_load assert
...
Conflicts:
erts/emulator/beam/bif.tab
|
|
* nox/ets-update_counter-4:
Create new BIF ets:update_counter/4
Allow 4-ary BIFs
OTP-12563
|
|
Add a check to enif_make_double to see if its double argument is
infinity or NaN, returning a badarg exception if it is. Change the
erl_nif documentation to specify that enif_make_double returns a
badarg exception if its double argument is either infinity or NaN. Add
tests to nif_SUITE for this change.
Add checks to the enif_make* functions for atoms to prevent the
creation of atoms whose name lengths are greater than the allowed
maximum atom length. The enif_make_atom and enif_make_atom_len
functions now return a badarg exception if the input string is too
long. The enif_make_existing_atom and enif_make_existing_atom_len
functions return false if the input string is too long. Change the
erl_nif documentation to reflect the changes to these functions. Add
tests to nif_SUITE for these changes.
Add a field to ErlNifEnv to track that a NIF has raised an exception
via enif_make_badarg. If a NIF calls enif_make_badarg but then ignores
its return value and instead tries to return a non-exception term as
its return value, the runtime still raises a badarg. This is needed to
prevent enif_make_badarg values resulting from calls to
enif_make_double, enif_make_atom, or enif_make_atom_len from being
erroneously stored within other terms and returned from a NIF. Calling
enif_make_badarg but not returning its return value has been
documented as being illegal ever since enif_make_badarg was added, but
the runtime has not enforced it until now. Add tests for regular and
dirty NIFs to ensure that calls to enif_make_badarg result in badarg
exceptions even if a NIF fails to return the result of
enif_make_badarg as its return value. Add documentation to
enif_make_badarg to specify that calling it raises a badarg even if a
NIF ignores its return value.
|
|
as shorthand for is_flatmap || is_hashmap
|
|
flatmap: Small map
hashmap: Large map
map: flatmap or hashmap
|
|
|
|
|
|
with over estimation of heap size.
|
|
|
|
|
|
Did not build a hashmap once the small limit was exceeded.
|
|
|
|
|
|
|
|
Conflicts:
erts/emulator/Makefile.in
erts/emulator/beam/bif.tab
erts/emulator/beam/erl_gc.c
erts/emulator/beam/erl_gc.h
erts/emulator/beam/erl_printf_term.c
erts/emulator/beam/erl_term.c
erts/emulator/beam/erl_term.h
|
|
* egil/beam/select_val/OTP-12555:
erts: Use linear search for small select_val arrays
|
|
|
|
For searching a key in an array we use linear search in arrays
up to 10 elements.
Selecting on tuple arity will always use linear search.
Instead of using two different instructions we assume selecting on
different tuple arities are always few in numbers.
|
|
and usage
|
|
* egil/fix-instruction-counter:
erts: Fix SMP for ERTS_OPCODE_COUNTER_SUPPORT
erts: Add icount build type for opcode counter
|
|
Cleanup macro code.
|
|
* sverk/bin-alloc-refactor:
erts: Fix gdb command etp-carrier-blocks for 32-bit
erts: Refactor binary allocation interface to also initialize Binary
|
|
except the reference counter 'refc', as different callers
have different strategies regarding the lifetime of the binary.
|
|
* maint:
add enif_schedule_nif() to NIF API
|
|
In the #erlang IRC channel Anthony Ramine once mentioned the idea of
allowing a NIF to use an emulator trap, similar to a BIF trap, to schedule
another NIF for execution. This is exactly how dirty NIFs were implemented
for Erlang/OTP 17.0, so this commit refactors and generalizes that dirty
NIF code to support a new enif_schedule_nif() API function.
The enif_schedule_nif() function allows a long-running NIF to be broken
into separate NIF invocations. The NIF first executes part of the
long-running task, then calls enif_schedule_nif() to schedule a NIF for
later execution to continue the task. Any number of NIFs can be scheduled
in this manner, one after another. Since the emulator regains control
between invocations, this helps avoid problems caused by native code tying
up scheduler threads for too long.
The enif_schedule_nif() function also replaces the original experimental
dirty NIF API. The function takes a flags parameter that a caller can use
to indicate the NIF should be scheduled onto either a dirty CPU scheduler
thread, a dirty I/O scheduler thread, or scheduled as a regular NIF on a
regular scheduler thread. With this change, the original experimental
enif_schedule_dirty_nif(), enif_schedule_dirty_nif_finalizer() and
enif_dirty_nif_finalizer() API functions are no longer needed and have been
removed. Explicit scheduling of a dirty NIF finalization function is no
longer necessary; if an application wants similar functionality, it can
have a dirty NIF just invoke enif_schedule_nif() to schedule a non-dirty
NIF to complete its task.
Lift the restriction that dirty NIFs can't call enif_make_badarg() to raise
an exception. This was a problem with the original dirty NIF API because it
forced developers to get and check all incoming arguments in a regular NIF,
and then schedule the dirty NIF which then had to get all the arguments
again. Now, the argument checking can be done in the dirty NIF and it can
call enif_make_badarg() itself to flag incorrect arguments.
Extend the ErlNifFunc struct with a new flags field that allows NIFs to be
declared as dirty. The default value for this field is 0, indicating a
regular NIF, so it's backwards compatible with all existing statically
initialized ErlNifFunc struct instances, and so such instances require no
code changes. Defining the flags field with a value of
ERL_NIF_DIRTY_JOB_CPU_BOUND indicates that the NIF should execute on a
dirty CPU scheduler thread, or defining it with a value of
ERL_NIF_DIRTY_JOB_IO_BOUND indicates that the NIF should execute on a dirty
I/O scheduler thread. Any other flags field value causes a NIF library
loading error.
Extend the ErlNifEntry struct with a new options field that indicates
whether a NIF library was built with support for optional features such as
dirty NIFs. When a NIF library is loaded, the runtime checks the options
field to ensure compatibility. If a NIF library built with dirty NIF
support is loaded into a runtime that does not support dirty NIFs, and the
library defines one or more ErlNifFunc entries with non-zero flags fields
indicating dirty NIFs, a NIF library loading error results. There is no
error if a NIF library built with dirty NIF support is loaded into a
runtime that does not support dirty NIFs but the library does not have any
dirty NIFs. It is also not an error if a library without dirty NIF support
is loaded into a runtime built with dirty NIF support.
Add documentation and tests for enif_schedule_nif().
|