Skip to content

Commit a88a02b

Browse files
committed
[GR-18163] Fix rb_gc_register_mark_object for Float and bignum values
PullRequest: truffleruby/4231
2 parents 355704c + a5e8ab2 commit a88a02b

File tree

6 files changed

+25
-5
lines changed

6 files changed

+25
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ Bug fixes:
88
* Fix repeated calling of methods `Dir#{each,each_child,children}` (#3464, @andrykonchin).
99
* Fix `IO#{wait,wait_readable,wait_writable}` methods and switch the current thread into a sleep state (@andrykonchin).
1010
* Fix `rb_global_variable()` for `Float` and bignum values during the `Init_` function (#3478, @eregon).
11+
* Fix `rb_gc_register_mark_object()` for `Float` and bignum values (#3502, @eregon, @andrykonchin).
1112
* Fix parsing literal floats when the locale does not use `.` for the decimal separator (e.g. `LANG=fr_FR.UTF-8`) (#3512, @eregon).
1213

1314
Compatibility:
15+
1416
* Move `IO#wait_readable`, `IO#wait_writable`, `IO#wait_priority` and `IO#wait` into core library (@andrykonchin).
1517
* Change assignment evaluation order for fully qualified constant and evaluate left-hand-side before right-hand-side (#3039, @andrykonchin).
1618
* Fix evaluation order for multi-assignment and evaluate left-hand-side before right-hand-side (@andrykonchin).
1719
* Add `Regexp.linear_time?` method (#3039, @andrykonchin).
18-
1920
* Allow null encoding pointer in `rb_enc_interned_str_cstr` (@thomasmarshall).
2021

2122
Performance:

lib/cext/ABI_check.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
17
1+
18

lib/truffle/truffle/cext.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,8 +1621,12 @@ def rb_gc
16211621

16221622
GC_ROOTS = []
16231623

1624-
def rb_gc_register_mark_object(obj)
1625-
GC_ROOTS.push obj
1624+
def rb_gc_register_mark_object(value)
1625+
# We save the ValueWrapper here and not the actual value/object, this is important for primitives like double and
1626+
# not-fixnum-long, as we need to preserve the handle by preserving the ValueWrapper of that handle.
1627+
# For those cases the primitive cannot itself reference its ValueWrapper, unlike RubyDynamicObject and ImmutableRubyObject.
1628+
wrapper = Primitive.cext_to_wrapper(value)
1629+
GC_ROOTS.push wrapper
16261630
end
16271631

16281632
def rb_gc_latest_gc_info(hash_or_key)

spec/ruby/optional/capi/ext/gc_spec.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ VALUE registered_after_rb_global_variable_bignum;
1616
VALUE registered_after_rb_global_variable_float;
1717
VALUE rb_gc_register_address_outside_init;
1818

19+
VALUE rb_gc_register_mark_object_not_referenced_float;
20+
1921
static VALUE registered_tagged_address(VALUE self) {
2022
return registered_tagged_value;
2123
}
@@ -90,6 +92,10 @@ static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) {
9092
return Qnil;
9193
}
9294

95+
static VALUE gc_spec_rb_gc_register_mark_object_not_referenced_float(VALUE self) {
96+
return rb_gc_register_mark_object_not_referenced_float;
97+
}
98+
9399
void Init_gc_spec(void) {
94100
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
95101

@@ -115,6 +121,9 @@ void Init_gc_spec(void) {
115121
registered_after_rb_global_variable_float = DBL2NUM(6.28);
116122
rb_global_variable(&registered_after_rb_global_variable_float);
117123

124+
rb_gc_register_mark_object_not_referenced_float = DBL2NUM(1.61);
125+
rb_gc_register_mark_object(rb_gc_register_mark_object_not_referenced_float);
126+
118127
rb_define_method(cls, "registered_tagged_address", registered_tagged_address, 0);
119128
rb_define_method(cls, "registered_reference_address", registered_reference_address, 0);
120129
rb_define_method(cls, "registered_before_rb_gc_register_address", get_registered_before_rb_gc_register_address, 0);
@@ -131,6 +140,7 @@ void Init_gc_spec(void) {
131140
rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0);
132141
rb_define_method(cls, "rb_gc_adjust_memory_usage", gc_spec_rb_gc_adjust_memory_usage, 1);
133142
rb_define_method(cls, "rb_gc_register_mark_object", gc_spec_rb_gc_register_mark_object, 1);
143+
rb_define_method(cls, "rb_gc_register_mark_object_not_referenced_float", gc_spec_rb_gc_register_mark_object_not_referenced_float, 0);
134144
rb_define_method(cls, "rb_gc_latest_gc_info", gc_spec_rb_gc_latest_gc_info, 1);
135145
}
136146

spec/ruby/optional/capi/gc_spec.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@
108108
it "can be called with an object" do
109109
@f.rb_gc_register_mark_object(Object.new).should be_nil
110110
end
111+
112+
it "keeps the value alive even if the value is not referenced by any Ruby object" do
113+
@f.rb_gc_register_mark_object_not_referenced_float.should == 1.61
114+
end
111115
end
112116

113117
describe "rb_gc_latest_gc_info" do

src/main/c/cext/gc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ VALUE rb_gc_latest_gc_info(VALUE key) {
6565
}
6666

6767
void rb_gc_register_mark_object(VALUE obj) {
68-
RUBY_CEXT_INVOKE_NO_WRAP("rb_gc_register_mark_object", obj);
68+
// No rb_tr_unwrap() here as the caller actually wants a ValueWrapper or a handle
69+
polyglot_invoke(RUBY_CEXT, "rb_gc_register_mark_object", obj);
6970
}
7071

7172
void* rb_tr_read_VALUE_pointer(VALUE *pointer) {

0 commit comments

Comments
 (0)