summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2020-09-22 17:02:15 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:23 -0400
commit5bcba2a5ee5d331f6979fcaff11ac00ee15d7508 (patch)
tree72b7dc8e6788949a6daf300b8dfa6d5a67123a0a
parent38601da27dde73c75ec052d2d6ca555da71ee00e (diff)
Add workaround for inserting into addr2insn mapping
-rw-r--r--ujit_compile.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/ujit_compile.c b/ujit_compile.c
index bfe75d1b7b..5980df59f5 100644
--- a/ujit_compile.c
+++ b/ujit_compile.c
@@ -64,7 +64,14 @@ addr2insn_bookkeeping(void *code_ptr, int insn)
const void * const translated_address = table[insn];
st_data_t encoded_insn_data;
if (st_lookup(rb_encoded_insn_data, (st_data_t)translated_address, &encoded_insn_data)) {
- st_insert(rb_encoded_insn_data, (st_data_t)code_ptr, encoded_insn_data);
+ // This is a roundabout way of doing an insert. Doing a plain insert can cause GC
+ // while inserting. While inserting, the table is in an inconsistent state and the
+ // GC can do a lookup in the table.
+ st_table *new_table = st_copy(rb_encoded_insn_data);
+ st_table *old_table = rb_encoded_insn_data;
+ st_insert(new_table, (st_data_t)code_ptr, encoded_insn_data);
+ rb_encoded_insn_data = new_table;
+ st_free_table(old_table);
}
else {
rb_bug("ujit: failed to find info for original instruction while dealing with addr2insn");