summaryrefslogtreecommitdiff
path: root/iseq.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2019-10-08 13:35:24 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2019-10-28 12:15:05 -0700
commitbbf3de22b6654642c923884b9e186e6412f1ba6a (patch)
tree56fa4dfac5f06ddf7303955fb03fa35b042a50da /iseq.c
parent339a891c7d9c56f27f10ed9a9e60f511f75da934 (diff)
Pin labels during disassembly
We need to ensure that labels are pinned while disassembling. If the compactor runs during disassembly, references to these labels could go bad, so this commit just ensures that the labels can't move until we're done.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2625
Diffstat (limited to 'iseq.c')
-rw-r--r--iseq.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/iseq.c b/iseq.c
index c9fef82aef..8285aadf9b 100644
--- a/iseq.c
+++ b/iseq.c
@@ -2099,6 +2099,12 @@ iseq_inspect(const rb_iseq_t *iseq)
}
}
+static const rb_data_type_t tmp_set = {
+ "tmpset",
+ {(void (*)(void *))rb_mark_set, (void (*)(void *))st_free_table, 0, 0,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
{
@@ -2112,6 +2118,7 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
size_t n;
enum {header_minlen = 72};
st_table *done_iseq = 0;
+ VALUE done_iseq_wrapper = Qnil;
const char *indent_str;
long indent_len;
@@ -2151,7 +2158,10 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
(int)entry->end, (int)entry->sp, (int)entry->cont);
if (entry->iseq && !(done_iseq && st_is_member(done_iseq, (st_data_t)entry->iseq))) {
rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check(entry->iseq), indent));
- if (!done_iseq) done_iseq = st_init_numtable();
+ if (!done_iseq) {
+ done_iseq = st_init_numtable();
+ done_iseq_wrapper = TypedData_Wrap_Struct(0, &tmp_set, done_iseq);
+ }
st_insert(done_iseq, (st_data_t)entry->iseq, (st_data_t)0);
indent_str = RSTRING_PTR(indent);
}
@@ -2231,7 +2241,7 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
rb_str_concat(str, rb_iseq_disasm_recursive(rb_iseq_check((rb_iseq_t *)isv), indent));
indent_str = RSTRING_PTR(indent);
}
- if (done_iseq) st_free_table(done_iseq);
+ RB_GC_GUARD(done_iseq_wrapper);
return str;
}
@@ -2544,6 +2554,12 @@ cdhash_each(VALUE key, VALUE value, VALUE ary)
return ST_CONTINUE;
}
+static const rb_data_type_t label_wrapper = {
+ "label_wrapper",
+ {(void (*)(void *))rb_mark_tbl, (void (*)(void *))st_free_table, 0, 0,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
iseq_data_to_ary(const rb_iseq_t *iseq)
{
@@ -2566,6 +2582,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
static ID insn_syms[VM_INSTRUCTION_SIZE/2]; /* w/o-trace only */
struct st_table *labels_table = st_init_numtable();
+ VALUE labels_wrapper = TypedData_Wrap_Struct(0, &label_wrapper, labels_table);
DECL_SYMBOL(top);
DECL_SYMBOL(method);
@@ -2841,8 +2858,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
pos += RARRAY_LENINT(ary); /* reject too huge data */
}
RB_GC_GUARD(nbody);
-
- st_free_table(labels_table);
+ RB_GC_GUARD(labels_wrapper);
rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq_body->param.size));
rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq_body->local_table_size));