summaryrefslogtreecommitdiff
path: root/erts/emulator/beam/emu/instrs.tab
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/emu/instrs.tab')
-rw-r--r--erts/emulator/beam/emu/instrs.tab24
1 files changed, 24 insertions, 0 deletions
diff --git a/erts/emulator/beam/emu/instrs.tab b/erts/emulator/beam/emu/instrs.tab
index 2c794aa4b0..88e6da9bf1 100644
--- a/erts/emulator/beam/emu/instrs.tab
+++ b/erts/emulator/beam/emu/instrs.tab
@@ -762,6 +762,30 @@ self(Dst) {
$Dst = c_p->common.id;
}
+i_update_record(Size, Src, Dst, Offset, Element) {
+ Eterm *untagged_source = tuple_val($Src);
+ Uint size_on_heap = $Size + 1;
+
+ /* Copy the entire tuple up-front, mimicking the behavior of the old
+ * setelement/3 + set_tuple_element method. This overwrites every field
+ * we're setting, but that cost is generally pretty small. */
+ sys_memcpy(HTOP, untagged_source, size_on_heap * sizeof(Eterm));
+ HTOP[$Offset] = $Element;
+
+ /* We stash the contents of the destination register in SCRATCH_X_REG in
+ * case it's used in subsequent `i_update_record_continue` instructions.
+ * The updates have been rewritten accordingly. */
+ reg[SCRATCH_X_REG] = $Dst;
+ $Dst = make_tuple(HTOP);
+
+ HTOP += size_on_heap;
+}
+
+i_update_record_continue(OffsetFromEnd, Element) {
+ Sint offset = -(Sint)$OffsetFromEnd;
+ HTOP[offset] = $Element;
+}
+
set_tuple_element(Element, Tuple, Offset) {
Eterm* p;