Skip to content

Commit 3e8f3b2

Browse files
committed
Implement memsize functions for wrapped structures.
1 parent 3fe0afa commit 3e8f3b2

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

lib/truffle/objspace.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ def dump_all(output: :file)
152152
module_function :dump_all
153153

154154
def memsize_of(object)
155-
Truffle::ObjSpace.memsize_of(object)
155+
unless Truffle::ObjSpace.has_sizer?(object)
156+
Truffle::ObjSpace.memsize_of(object)
157+
else
158+
Truffle::ObjSpace.memsize_of(object) + Truffle::ObjSpace.sizer(object).call
159+
end
156160
end
157161
module_function :memsize_of
158162

lib/truffle/truffle/cext.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1415,13 +1415,14 @@ def rb_data_object_wrap(ruby_class, data, mark, free)
14151415
object
14161416
end
14171417

1418-
def rb_data_typed_object_wrap(ruby_class, data, data_type, mark, free)
1418+
def rb_data_typed_object_wrap(ruby_class, data, data_type, mark, free, size)
14191419
ruby_class = Object if Truffle::Interop.null?(ruby_class)
14201420
object = BASIC_OBJECT_ALLOCATE.bind(ruby_class).call
14211421
data_holder = DataHolder.new(data)
14221422
hidden_variable_set object, :data_type, data_type
14231423
hidden_variable_set object, :data_holder, data_holder
14241424
ObjectSpace.define_finalizer object, data_finalizer(free, data_holder) unless free.nil?
1425+
Truffle::ObjSpace.define_sizer object, data_sizer(size, data_holder) unless size.nil?
14251426
define_marker object, data_marker(mark, data_holder) unless mark.nil?
14261427
object
14271428
end
@@ -1444,6 +1445,14 @@ def data_marker(mark, data_holder)
14441445
}
14451446
end
14461447

1448+
def data_sizer(sizer, data_holder)
1449+
# In a separate method to avoid capturing the object
1450+
raise unless sizer.respond_to?(:call)
1451+
proc {
1452+
Truffle.invoke_primitive(:interop_call_c_with_mutex, sizer, [data_holder.data])
1453+
}
1454+
end
1455+
14471456
def rb_ruby_verbose_ptr
14481457
$VERBOSE
14491458
end

src/main/c/cext/ruby.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2838,7 +2838,7 @@ VALUE rb_data_object_alloc_managed(VALUE klass, size_t size, RUBY_DATA_FUNC dmar
28382838

28392839
VALUE rb_data_typed_object_wrap(VALUE ruby_class, void *data, const rb_data_type_t *data_type) {
28402840
return rb_tr_wrap(polyglot_invoke(RUBY_CEXT, "rb_data_typed_object_wrap",
2841-
rb_tr_unwrap(ruby_class), data, data_type, data_type->function.dmark, rb_tr_free_function(data_type->function.dfree)));
2841+
rb_tr_unwrap(ruby_class), data, data_type, data_type->function.dmark, rb_tr_free_function(data_type->function.dfree), data_type->function.dsize));
28422842
}
28432843

28442844
VALUE rb_data_typed_object_zalloc(VALUE ruby_class, size_t size, const rb_data_type_t *data_type) {

src/main/java/org/truffleruby/Layouts.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public abstract class Layouts {
104104
public static final HiddenKey ASSOCIATED_IDENTIFIER = new HiddenKey("associated");
105105
public static final HiddenKey FINALIZER_REF_IDENTIFIER = new HiddenKey("finalizerRef");
106106
public static final HiddenKey MARKED_OBJECTS_IDENTIFIER = new HiddenKey("marked_objects");
107+
public static final HiddenKey MEMSIZER_IDENTIFIER = new HiddenKey("memsizer");
107108
public static final HiddenKey VALUE_WRAPPER_IDENTIFIER = new HiddenKey("value_wrapper");
108109

109110
// Generated layouts

src/main/java/org/truffleruby/stdlib/ObjSpaceNodes.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import org.truffleruby.core.regexp.MatchDataNodes.ValuesNode;
2020
import org.truffleruby.core.string.StringOperations;
2121
import org.truffleruby.language.objects.ObjectGraph;
22+
import org.truffleruby.language.objects.ReadObjectFieldNode;
23+
import org.truffleruby.language.objects.ReadObjectFieldNodeGen;
24+
import org.truffleruby.language.objects.WriteObjectFieldNode;
25+
import org.truffleruby.language.objects.WriteObjectFieldNodeGen;
2226

2327
import java.util.Set;
2428

@@ -65,7 +69,40 @@ public int memsizeOfObject(DynamicObject object) {
6569
public int memsize(Object object) {
6670
return 0;
6771
}
72+
}
73+
74+
@CoreMethod(names = "has_sizer?", isModuleFunction = true, required = 1)
75+
public abstract static class HasMemSizer extends CoreMethodArrayArgumentsNode {
76+
77+
@Child private ReadObjectFieldNode setSizerNode = ReadObjectFieldNodeGen.create(Layouts.MEMSIZER_IDENTIFIER, nil());
78+
79+
@Specialization
80+
public boolean hasSizer(DynamicObject object) {
81+
return setSizerNode.execute(object) != nil();
82+
}
83+
}
84+
85+
@CoreMethod(names = "sizer", isModuleFunction = true, required = 1)
86+
public abstract static class GetMemSizer extends CoreMethodArrayArgumentsNode {
87+
88+
@Child private ReadObjectFieldNode setSizerNode = ReadObjectFieldNodeGen.create(Layouts.MEMSIZER_IDENTIFIER, nil());
6889

90+
@Specialization
91+
public Object hasSizer(DynamicObject object) {
92+
return setSizerNode.execute(object);
93+
}
94+
}
95+
96+
@CoreMethod(names = "define_sizer", isModuleFunction = true, required = 2)
97+
public abstract static class DefineMemSizer extends CoreMethodArrayArgumentsNode {
98+
99+
@Child private WriteObjectFieldNode setSizerNode = WriteObjectFieldNodeGen.create(Layouts.MEMSIZER_IDENTIFIER);
100+
101+
@Specialization
102+
public DynamicObject defineSizer(DynamicObject object, DynamicObject sizer) {
103+
setSizerNode.write(object, sizer);
104+
return nil();
105+
}
69106
}
70107

71108
@CoreMethod(names = "adjacent_objects", isModuleFunction = true, required = 1)

0 commit comments

Comments
 (0)