Skip to content

Commit

Permalink
[GR-18163] Fix rb_integer_pack() for values between 2**62 and 2**63
Browse files Browse the repository at this point in the history
PullRequest: truffleruby/4089
  • Loading branch information
eregon committed Dec 11, 2023
2 parents 5a2ad5d + e4592d9 commit e415105
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Bug fixes:
* Fix `IO.copy_stream` with a `Tempfile` destination (#3280, @eregon).
* Fix `Regexp.union` negotiating the wrong result encoding (#3287, @nirvdrum, @simonlevasseur).
* Fix `Proc#parameters` and return all the numbered parameters lower than the used explicitly ones (@andrykonchin).
* Fix some C API functions which were failing when called with Ruby values represented as Java primitives (#3352, @eregon).

Compatibility:

Expand Down
2 changes: 1 addition & 1 deletion lib/cext/ABI_check.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6
7
40 changes: 40 additions & 0 deletions lib/truffle/truffle/cext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -424,16 +424,44 @@ def RB_OBJ_TAINTABLE(object)
end
end

def rb_obj_clone(object)
object.clone
end

def rb_obj_dup(object)
object.dup
end

def rb_obj_encoding(object)
object.encoding
end

FREEZE_METHOD = Kernel.instance_method :freeze

def rb_obj_freeze(obj)
FREEZE_METHOD.bind(obj).call
end

def rb_obj_frozen_p(object)
object.frozen?
end

def rb_obj_id(object)
object.object_id
end

def rb_float_new(value)
value.to_f
end

def rb_flt_rationalize(value)
value.rationalize
end

def rb_flt_rationalize_with_prec(value, prec)
value.rationalize(prec)
end

def rb_absint_singlebit_p(val)
Primitive.rb_int_singlebit_p(val.abs)
end
Expand Down Expand Up @@ -556,6 +584,10 @@ def rb_class_of(object)
Primitive.metaclass(object)
end

def rb_singleton_class(object)
object.singleton_class
end

def rb_class_real(ruby_class)
while ruby_class.singleton_class?
ruby_class = ruby_class.superclass
Expand Down Expand Up @@ -844,6 +876,10 @@ def rb_intern(str)
Primitive.string_to_symbol(str, true)
end

def rb_int_cmp(a, b)
a <=> b
end

def rb_int_positive_pow(a, b)
a ** b
end
Expand Down Expand Up @@ -1379,6 +1415,10 @@ def rb_equal(a, b)
Primitive.same_or_equal?(a, b)
end

def rb_tr_obj_equal(a, b)
Primitive.equal?(a, b)
end

def rb_obj_call_init(obj, args, block)
obj.__send__ :initialize, *args, &block
end
Expand Down
17 changes: 17 additions & 0 deletions spec/ruby/optional/capi/integer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,23 @@
result.should == -1
@words.should == "\x11\x32\x54\x76\x98\xBA\xDC\xFE"
end

it "converts numbers near the fixnum limit successfully" do
result = @s.rb_integer_pack(0x7123_4567_89ab_cdef, @words, 1, 8, 0,
CApiIntegerSpecs::NATIVE|CApiIntegerSpecs::PACK_2COMP)
result.should == 1
@words.should == "\xEF\xCD\xAB\x89\x67\x45\x23\x71"

result = @s.rb_integer_pack(2**62-1, @words, 1, 8, 0,
CApiIntegerSpecs::NATIVE|CApiIntegerSpecs::PACK_2COMP)
result.should == 1
@words.should == "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"

result = @s.rb_integer_pack(2**63-1, @words, 1, 8, 0,
CApiIntegerSpecs::NATIVE|CApiIntegerSpecs::PACK_2COMP)
result.should == 1
@words.should == "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/main/c/cext/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ VALUE rb_class_of(VALUE object) {
}

VALUE rb_singleton_class(VALUE object) {
return RUBY_INVOKE(object, "singleton_class");
return RUBY_CEXT_INVOKE("rb_singleton_class", object);
}

VALUE rb_obj_alloc(VALUE ruby_class) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/c/cext/define.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void rb_define_global_function(const char *name, VALUE (*function)(ANYARGS), int

#undef rb_define_singleton_method
void rb_define_singleton_method(VALUE object, const char *name, VALUE (*function)(ANYARGS), int argc) {
rb_define_method(RUBY_INVOKE(object, "singleton_class"), name, function, argc);
rb_define_method(rb_singleton_class(object), name, function, argc);
}

void rb_define_alias(VALUE module, const char *new_name, const char *old_name) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/c/cext/encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ int rb_enc_to_index(rb_encoding *enc) {
}

VALUE rb_obj_encoding(VALUE obj) {
return RUBY_INVOKE(obj, "encoding");
return RUBY_CEXT_INVOKE("rb_obj_encoding", obj);
}

int rb_to_encoding_index(VALUE enc) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/c/cext/integer.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ int rb_integer_pack(VALUE value, void *words, size_t numwords, size_t wordsize,
long l = NUM2LONG(value);
sign = (l > 0) - (l < 0);
} else {
sign = polyglot_as_i32(polyglot_invoke(rb_tr_unwrap(value), "<=>", 0));
sign = polyglot_as_i32(RUBY_CEXT_INVOKE_NO_WRAP("rb_int_cmp", value, INT2FIX(0)));
}
int bytes_needed = size / 8 + (size % 8 == 0 ? 0 : 1);
int words_needed = bytes_needed / wordsize + (bytes_needed % wordsize == 0 ? 0 : 1);
Expand Down
8 changes: 4 additions & 4 deletions src/main/c/cext/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ VALUE rb_obj_reveal(VALUE obj, VALUE klass) {
}

VALUE rb_obj_clone(VALUE obj) {
return RUBY_INVOKE(obj, "clone");
return RUBY_CEXT_INVOKE("rb_obj_clone", obj);
}

VALUE rb_obj_dup(VALUE object) {
return RUBY_INVOKE(object, "dup");
return RUBY_CEXT_INVOKE("rb_obj_dup", object);
}

VALUE rb_obj_id(VALUE object) {
return RUBY_INVOKE(object, "object_id");
return RUBY_CEXT_INVOKE("rb_obj_id", object);
}

// The semantics of SameOrEqualNode: a.equal?(b) || a == b
Expand All @@ -138,7 +138,7 @@ void rb_obj_call_init(VALUE object, int argc, const VALUE *argv) {
// frozen status

VALUE rb_obj_frozen_p(VALUE object) {
return RUBY_INVOKE(object, "frozen?");
return RUBY_CEXT_INVOKE("rb_obj_frozen_p", object);
}

VALUE rb_obj_freeze(VALUE object) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/c/cext/rational.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ VALUE rb_rational_den(VALUE rat) {
}

VALUE rb_flt_rationalize_with_prec(VALUE value, VALUE precision) {
return RUBY_INVOKE(value, "rationalize", precision);
return RUBY_CEXT_INVOKE("rb_flt_rationalize_with_prec", value, precision);
}

VALUE rb_flt_rationalize(VALUE value) {
return RUBY_INVOKE(value, "rationalize");
return RUBY_CEXT_INVOKE("rb_flt_rationalize", value);
}
2 changes: 1 addition & 1 deletion src/main/c/cext/truffleruby.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ VALUE rb_java_to_string(VALUE obj) {

// BasicObject#equal?
int rb_tr_obj_equal(VALUE first, VALUE second) {
return RTEST(RUBY_INVOKE(first, "equal?", second));
return RTEST(RUBY_CEXT_INVOKE("rb_tr_obj_equal", first, second));
}

void rb_tr_warn_va_list(const char *fmt, va_list args) {
Expand Down

0 comments on commit e415105

Please sign in to comment.