aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_emu.c
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2014-02-12 17:04:26 +0100
committerBjörn-Egil Dahlberg <[email protected]>2014-02-19 15:32:17 +0100
commit3e206565c2032a24b03ca13c313d1879d74dfec6 (patch)
tree74d358a03755d40763e3a594509b3ed1530a30ac /erts/emulator/beam/beam_emu.c
parent210dbf68a62794b51b74337381cd87424a46b2a5 (diff)
downloadotp-3e206565c2032a24b03ca13c313d1879d74dfec6.tar.gz
otp-3e206565c2032a24b03ca13c313d1879d74dfec6.tar.bz2
otp-3e206565c2032a24b03ca13c313d1879d74dfec6.zip
erts: Introduce new instructions for combined key fetches
Diffstat (limited to 'erts/emulator/beam/beam_emu.c')
-rw-r--r--erts/emulator/beam/beam_emu.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 1ae413d46e..6f295530b9 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -2355,6 +2355,126 @@ void process_main(void)
Next(4+Arg(3));
}
+ OpCase(i_has_map_fields_fsI): {
+ map_t* mp;
+ Eterm map;
+ Eterm field;
+ Eterm *ks;
+ BeamInstr* fs;
+ Uint sz,n;
+
+ GetArg1(1, map);
+
+ /* this instruction assumes Arg1 is a map,
+ * i.e. that it follows a test is_map if needed.
+ */
+
+ mp = (map_t *)map_val(map);
+ sz = map_get_size(mp);
+
+ if (sz == 0) {
+ SET_I((BeamInstr *) Arg(0));
+ goto has_map_fields_fail;
+ }
+
+ ks = map_get_keys(mp);
+ n = (Uint)Arg(2);
+ fs = &Arg(3); /* pattern fields */
+
+ ASSERT(n>0);
+
+ while(sz) {
+ field = (Eterm)*fs;
+ if (EQ(field,*ks)) {
+ n--;
+ fs++;
+ if (n == 0) break;
+ }
+ ks++; sz--;
+ }
+
+ if (n) {
+ SET_I((BeamInstr *) Arg(0));
+ goto has_map_fields_fail;
+ }
+
+ I += 4 + Arg(2);
+has_map_fields_fail:
+ ASSERT(VALID_INSTR(*I));
+ Goto(*I);
+ }
+
+#define PUT_TERM_REG(term, desc) \
+do { \
+ switch ((desc) & _TAG_IMMED1_MASK) { \
+ case (R_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
+ r(0) = (term); \
+ break; \
+ case (X_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
+ x((desc) >> _TAG_IMMED1_SIZE) = (term); \
+ break; \
+ case (Y_REG_DEF << _TAG_PRIMARY_SIZE) | TAG_PRIMARY_HEADER: \
+ y((desc) >> _TAG_IMMED1_SIZE) = (term); \
+ break; \
+ default: \
+ ASSERT(0); \
+ break; \
+ } \
+} while(0)
+
+ OpCase(i_get_map_elements_fsI): {
+ Eterm map;
+ map_t *mp;
+ Eterm field;
+ Eterm *ks;
+ Eterm *vs;
+ BeamInstr *fs;
+ Uint sz,n;
+
+ GetArg1(1, map);
+
+ /* this instruction assumes Arg1 is a map,
+ * i.e. that it follows a test is_map if needed.
+ */
+
+ mp = (map_t *)map_val(map);
+ sz = map_get_size(mp);
+
+ if (sz == 0) {
+ SET_I((BeamInstr *) Arg(0));
+ goto get_map_elements_fail;
+ }
+
+ n = (Uint)Arg(2) / 2;
+ fs = &Arg(3); /* pattern fields and target registers */
+ ks = map_get_keys(mp);
+ vs = map_get_values(mp);
+
+ while(sz) {
+ field = (Eterm)*fs;
+ if (EQ(field,*ks)) {
+ PUT_TERM_REG(*vs, fs[1]);
+ n--;
+ fs += 2;
+ /* no more values to fetch, we are done */
+ if (n == 0) break;
+ }
+ ks++; sz--;
+ vs++;
+ }
+
+ if (n) {
+ SET_I((BeamInstr *) Arg(0));
+ goto get_map_elements_fail;
+ }
+
+ I += 4 + Arg(2);
+get_map_elements_fail:
+ ASSERT(VALID_INSTR(*I));
+ Goto(*I);
+ }
+#undef PUT_TERM_REG
+
OpCase(update_map_assoc_jsdII): {
Eterm res;
Eterm map;