aboutsummaryrefslogtreecommitdiffstats
path: root/iseq.c
diff options
context:
space:
mode:
authorGannon McGibbon <gannon.mcgibbon@gmail.com>2024-03-22 15:38:28 -0500
committerPeter Zhu <peter@peterzhu.ca>2024-03-25 10:43:12 -0400
commita31ca3500d995b6706f94ff72166d699c5faeb27 (patch)
tree7a7ec25e4961f69d79916720ade85310af1d296e /iseq.c
parent552647175e8319aa7cc117d418f35ed761fdb822 (diff)
downloadruby-a31ca3500d995b6706f94ff72166d699c5faeb27.tar.gz
Mark iseq structs with rb_gc_mark_movable
Using rb_gc_mark_movable and a reference update function, we can make instruction sequences movable in memory, and avoid pinning compiled iseqs. ``` require "objspace" iseqs = [] GC.disable 50_000.times do iseqs << RubyVM::InstructionSequence.compile("") end GC.enable GC.compact p ObjectSpace.dump_all(output: :string).lines.grep(/"pinned":true/).count ``` Co-authored-by: Peter Zhu <peter@peterzhu.ca>
Diffstat (limited to 'iseq.c')
-rw-r--r--iseq.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/iseq.c b/iseq.c
index 057e047ef9..d00cc9e9cc 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1386,18 +1386,30 @@ rb_iseq_remove_coverage_all(void)
static void
iseqw_mark(void *ptr)
{
- rb_gc_mark((VALUE)ptr);
+ rb_gc_mark_movable(*(VALUE *)ptr);
}
static size_t
iseqw_memsize(const void *ptr)
{
- return rb_iseq_memsize((const rb_iseq_t *)ptr);
+ return rb_iseq_memsize(*(const rb_iseq_t **)ptr);
+}
+
+static void
+iseqw_ref_update(void *ptr)
+{
+ VALUE *vptr = ptr;
+ *vptr = rb_gc_location(*vptr);
}
static const rb_data_type_t iseqw_data_type = {
"T_IMEMO/iseq",
- {iseqw_mark, NULL, iseqw_memsize,},
+ {
+ iseqw_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ iseqw_memsize,
+ iseqw_ref_update,
+ },
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};
@@ -1408,11 +1420,9 @@ iseqw_new(const rb_iseq_t *iseq)
return iseq->wrapper;
}
else {
- union { const rb_iseq_t *in; void *out; } deconst;
- VALUE obj;
- deconst.in = iseq;
- obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out);
- RB_OBJ_WRITTEN(obj, Qundef, iseq);
+ rb_iseq_t **ptr;
+ VALUE obj = TypedData_Make_Struct(rb_cISeq, rb_iseq_t *, &iseqw_data_type, ptr);
+ RB_OBJ_WRITE(obj, ptr, iseq);
/* cache a wrapper object */
RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj);
@@ -1736,7 +1746,9 @@ iseqw_s_compile_option_get(VALUE self)
static const rb_iseq_t *
iseqw_check(VALUE iseqw)
{
- rb_iseq_t *iseq = DATA_PTR(iseqw);
+ rb_iseq_t **iseq_ptr;
+ TypedData_Get_Struct(iseqw, rb_iseq_t *, &iseqw_data_type, iseq_ptr);
+ rb_iseq_t *iseq = *iseq_ptr;
if (!ISEQ_BODY(iseq)) {
rb_ibf_load_iseq_complete(iseq);