aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/map_instrs.tab
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-08-15 13:34:45 +0200
committerBjörn Gustavsson <[email protected]>2017-08-15 15:56:09 +0200
commit17bb6bfa8d435300ee2205f1e0c20b0c6b50591a (patch)
tree0653a31031c4f17dd65d8ff3d6f19594cd1788cd /erts/emulator/beam/map_instrs.tab
parent589b8769a01511f1e95f8e6aab301aa5c223bc09 (diff)
downloadotp-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/beam/map_instrs.tab')
-rw-r--r--erts/emulator/beam/map_instrs.tab27
1 files changed, 11 insertions, 16 deletions
diff --git a/erts/emulator/beam/map_instrs.tab b/erts/emulator/beam/map_instrs.tab
index 7f9346d029..30c3d7743f 100644
--- a/erts/emulator/beam/map_instrs.tab
+++ b/erts/emulator/beam/map_instrs.tab
@@ -19,10 +19,12 @@
// %CopyrightEnd%
//
-BADMAP(Fail, Map) {
- c_p->freason = BADMAP;
- c_p->fvalue = $Map;
- $FAIL_HEAD_OR_BODY($Fail);
+ensure_map(Map) {
+ if (is_not_map($Map)) {
+ c_p->freason = BADMAP;
+ c_p->fvalue = $Map;
+ $FAIL_BODY();
+ }
}
new_map(Dst, Live, N) {
@@ -123,7 +125,7 @@ i_get_map_elements(Fail, Src, N) {
}
}
-update_map_assoc(Fail, Src, Dst, Live, N) {
+update_map_assoc(Src, Dst, Live, N) {
Eterm res;
Eterm map;
@@ -131,17 +133,10 @@ update_map_assoc(Fail, Src, Dst, Live, N) {
HEAVY_SWAPOUT;
res = update_map_assoc(c_p, reg, map, I);
HEAVY_SWAPIN;
- if (is_value(res)) {
- $REFRESH_GEN_DEST();
- $Dst = res;
- $NEXT($NEXT_INSTRUCTION+$N);
- } else {
- /*
- * This can only happen if the code was compiled
- * with the compiler in OTP 17.
- */
- $BADMAP($Fail, map);
- }
+ ASSERT(is_value(res));
+ $REFRESH_GEN_DEST();
+ $Dst = res;
+ $NEXT($NEXT_INSTRUCTION+$N);
}
update_map_exact(Fail, Src, Dst, Live, N) {