diff options
author | Björn Gustavsson <[email protected]> | 2017-08-15 13:34:45 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2017-08-15 15:56:09 +0200 |
commit | 17bb6bfa8d435300ee2205f1e0c20b0c6b50591a (patch) | |
tree | 0653a31031c4f17dd65d8ff3d6f19594cd1788cd /erts/emulator/test | |
parent | 589b8769a01511f1e95f8e6aab301aa5c223bc09 (diff) | |
download | otp-17bb6bfa8d435300ee2205f1e0c20b0c6b50591a.tar.gz otp-17bb6bfa8d435300ee2205f1e0c20b0c6b50591a.tar.bz2 otp-17bb6bfa8d435300ee2205f1e0c20b0c6b50591a.zip |
Slightly optimize updating of maps
The instruction put_map_assoc/5 (used for updating a map) has a
failure operand, but it can't actually fail provided that its "map"
argument is a map.
The following code:
M#{key=>value}.
will be compiled to:
{test,is_map,{f,3},[{x,0}]}.
{line,[...]}.
{put_map_assoc,{f,0},{x,0},{x,0},1,{list,[{atom,key},{atom,value}]}}.
return.
{label,3}.
%% Code that produces a 'badmap' exception follows.
Because of the is_map instruction, {x,0} always contains a map when
the put_map_assoc instruction is executed. Therefore we can remove
the failure operand. That will save one word, and also eliminate
two tests at run-time.
The only problem is that the compiler in OTP 17 did not emit a
is_map instruction before the put_map_assoc instruction. Therefore,
we must add an instruction that tests for a map if the code was
compiled with the OTP 17 compiler.
Unfortunately, there is no safe and relatively easy way to known that
the OTP 17 compiler was used, so we will check whether a compiler
before OTP 20 was used. OTP 20 introduced a new chunk type for atoms,
which is trivial to check.
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/map_SUITE_data/badmap_17.beam | bin | 592 -> 1192 bytes | |||
-rw-r--r-- | erts/emulator/test/map_SUITE_data/badmap_17.erl | 36 |
2 files changed, 34 insertions, 2 deletions
diff --git a/erts/emulator/test/map_SUITE_data/badmap_17.beam b/erts/emulator/test/map_SUITE_data/badmap_17.beam Binary files differindex 277fc34b94..6f79bb8c2c 100644 --- a/erts/emulator/test/map_SUITE_data/badmap_17.beam +++ b/erts/emulator/test/map_SUITE_data/badmap_17.beam diff --git a/erts/emulator/test/map_SUITE_data/badmap_17.erl b/erts/emulator/test/map_SUITE_data/badmap_17.erl index 0ec65e0e33..887fc2e5e3 100644 --- a/erts/emulator/test/map_SUITE_data/badmap_17.erl +++ b/erts/emulator/test/map_SUITE_data/badmap_17.erl @@ -1,7 +1,7 @@ -module(badmap_17). -export([update/1]). -%% Compile this source file with OTP 17. +%% Compile this source file with OTP 17.0. update(Map) -> try @@ -17,10 +17,42 @@ update(Map) -> catch error:{badmap,Map} -> ok - end. + end, + try + update_3(Map), + error(update_did_not_fail) + catch + error:{badmap,Map} -> + ok + end, + ok = update_4(Map), + ok = update_5(Map), + ok. update_1(M) -> M#{a=>42}. update_2(M) -> M#{a:=42}. + +update_3(M) -> + id(M), + M#{a=>42}. + +update_4(M) when M#{a=>b} =:= M -> + did_not_fail; +update_4(_) -> + ok. + +update_5(M) -> + id(M), + case id(true) of + true when M#{a=>b} =:= M -> + did_not_fail; + true -> + ok + end. + +id(I) -> + I. + |