diff options
Diffstat (limited to 'erts/emulator/beam/emu/instrs.tab')
-rw-r--r-- | erts/emulator/beam/emu/instrs.tab | 24 |
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; |