aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_emu.c
diff options
context:
space:
mode:
authorMichal Muskala <[email protected]>2017-07-01 17:19:52 +0200
committerMichal Muskala <[email protected]>2017-07-06 11:42:52 +0200
commit245aa4ed9b41aa601784598b0b3286d29b6d0085 (patch)
treede5448198979b0ccdc610883d4bcaafab326f0de /erts/emulator/beam/beam_emu.c
parente8a2cae09282b25a8eda9b6f04876e23a854336b (diff)
downloadotp-245aa4ed9b41aa601784598b0b3286d29b6d0085.tar.gz
otp-245aa4ed9b41aa601784598b0b3286d29b6d0085.tar.bz2
otp-245aa4ed9b41aa601784598b0b3286d29b6d0085.zip
Introduce new_small_map_lit op
Take advantage of the fact that small maps have a tuple for keys. When new map is constructed and all keys are literals, we can construct the entire keys tuple as a literal. This should reduce the memory of maps created with literal keys almost by half, since they all can share the same keys tuple.
Diffstat (limited to 'erts/emulator/beam/beam_emu.c')
-rw-r--r--erts/emulator/beam/beam_emu.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 27d19d2504..039ce3fa24 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1080,6 +1080,7 @@ static BeamInstr* apply_fun(Process* p, Eterm fun,
static Eterm new_fun(Process* p, Eterm* reg,
ErlFunEntry* fe, int num_free) NOINLINE;
static Eterm new_map(Process* p, Eterm* reg, BeamInstr* I) NOINLINE;
+static Eterm new_small_map_lit(Process* p, Eterm* reg, Uint* n_exp, BeamInstr* I) NOINLINE;
static Eterm update_map_assoc(Process* p, Eterm* reg,
Eterm map, BeamInstr* I) NOINLINE;
static Eterm update_map_exact(Process* p, Eterm* reg,
@@ -2461,6 +2462,17 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array)
Next(3+Arg(2));
}
+ OpCase(i_new_small_map_lit_dIq): {
+ Eterm res;
+ Uint n;
+
+ HEAVY_SWAPOUT;
+ res = new_small_map_lit(c_p, reg, &n, I-1);
+ HEAVY_SWAPIN;
+ StoreResult(res, Arg(0));
+ Next(3+n);
+ }
+
#define PUT_TERM_REG(term, desc) \
do { \
switch (loader_tag(desc)) { \
@@ -7035,6 +7047,44 @@ new_map(Process* p, Eterm* reg, BeamInstr* I)
}
static Eterm
+new_small_map_lit(Process* p, Eterm* reg, Uint* n_exp, BeamInstr* I)
+{
+ Eterm* keys = tuple_val(Arg(3));
+ Uint n = arityval(*keys);
+ Uint need = n + 1 /* hdr */ + 1 /*size*/ + 1 /* ptr */ + 1 /* arity */;
+ Uint i;
+ BeamInstr *ptr;
+ flatmap_t *mp;
+ Eterm *mhp;
+ Eterm *E;
+
+ *n_exp = n;
+ ptr = &Arg(4);
+
+ ASSERT(n <= MAP_SMALL_MAP_LIMIT);
+
+ if (HeapWordsLeft(p) < need) {
+ erts_garbage_collect(p, need, reg, Arg(2));
+ }
+
+ mhp = p->htop;
+ E = p->stop;
+
+ mp = (flatmap_t *)mhp; mhp += MAP_HEADER_FLATMAP_SZ;
+ mp->thing_word = MAP_HEADER_FLATMAP;
+ mp->size = n;
+ mp->keys = Arg(3);
+
+ for (i = 0; i < n; i++) {
+ GET_TERM(*ptr++, *mhp++);
+ }
+
+ p->htop = mhp;
+
+ return make_flatmap(mp);
+}
+
+static Eterm
update_map_assoc(Process* p, Eterm* reg, Eterm map, BeamInstr* I)
{
Uint n;