Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3755,7 +3755,7 @@ rb_gc_register_address(VALUE *addr)
RB_VM_LOCKING() {
if (vm->global_object_list_size == vm->global_object_list_capa) {
size_t new_capa = vm->global_object_list_capa ? vm->global_object_list_capa * 2 : 64;
vm->global_object_list = SIZED_REALLOC_N(vm->global_object_list, VALUE *, new_capa, vm->global_object_list_capa);
SIZED_REALLOC_N(vm->global_object_list, VALUE *, new_capa, vm->global_object_list_capa);
vm->global_object_list_capa = new_capa;
}

Expand Down
43 changes: 31 additions & 12 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,19 +385,31 @@ rb_f_binding(VALUE self)
}

/*
* call-seq:
* binding.eval(string [, filename [,lineno]]) -> obj
* call-seq:
* binding.eval(string, filename = default_filename, lineno = 1) -> obj
*
* Evaluates the Ruby expression(s) in <em>string</em>, in the
* <em>binding</em>'s context. If the optional <em>filename</em> and
* <em>lineno</em> parameters are present, they will be used when
* reporting syntax errors.
* Evaluates the Ruby expression(s) in +string+ in the context of
* +self+. Returns the result of the last expression:
*
* def get_binding(param)
* binding
* end
* def get_binding(param) = binding
* b = get_binding("hello")
* b.eval("param") #=> "hello"
*
* If the optional +filename+ is given, it will be used as the
* filename of the evaluation (for <tt>__FILE__</tt> and errors).
* Otherwise, it will default to <tt>(eval at __FILE__:__LINE__)</tt>
* where <tt>__FILE__</tt> and <tt>__LINE__</tt> are the filename and
* line number of the caller, respectively:
*
* b.eval("puts __FILE__") # => "(eval at test.rb:4)"
* b.eval("puts __FILE__", "foobar.rb") # => "foobar.rb"
*
* If the optional +lineno+ is given, it will be used as the
* line number of the evaluation (for <tt>__LINE__</tt> and errors).
* Otherwise, it will default to 1:
*
* b.eval("puts __LINE__") # => 1
* b.eval("puts __LINE__", "foobar.rb", 10) # => 10
*/

static VALUE
Expand Down Expand Up @@ -1853,6 +1865,8 @@ mnew_missing_by_name(VALUE klass, VALUE obj, VALUE *name, int scope, VALUE mclas
return mnew_missing(klass, obj, SYM2ID(vid), mclass);
}

VALUE rb_zsuper_to_super(int argc, VALUE *argv, VALUE self);

static VALUE
mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
VALUE obj, ID id, VALUE mclass, int scope, int error)
Expand All @@ -1878,8 +1892,9 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
rb_print_inaccessible(klass, id, visi);
}
}
if (me->def->type == VM_METHOD_TYPE_ZSUPER) {
if (me->defined_class) {
if (me->def->type == VM_METHOD_TYPE_ZSUPER ||
(me->def->type == VM_METHOD_TYPE_CFUNC && me->def->body.cfunc.func == (rb_cfunc_t)rb_zsuper_to_super)) {
if (me->def->type == VM_METHOD_TYPE_ZSUPER && me->defined_class) {
VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class));
id = me->def->original_id;
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass);
Expand Down Expand Up @@ -3071,7 +3086,11 @@ original_method_entry(VALUE mod, ID id)

while ((me = rb_method_entry(mod, id)) != 0) {
const rb_method_definition_t *def = me->def;
if (def->type != VM_METHOD_TYPE_ZSUPER) break;

if (def->type != VM_METHOD_TYPE_ZSUPER &&
(def->type != VM_METHOD_TYPE_CFUNC ||
def->body.cfunc.func != (rb_cfunc_t)rb_zsuper_to_super)) break;

mod = RCLASS_SUPER(me->owner);
id = def->original_id;
}
Expand Down
27 changes: 27 additions & 0 deletions test/ruby/test_refinement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,33 @@ def a = :b
end
end

def test_zsuper_refinement_method_arity_and_parameters
assert_separately([], <<-"end;")
class A
private def a(b) = b
end

class B < A
public :a
end

module R
refine A do
public :a
end
end
using R

m = B.instance_method(:a)
assert_equal(1, m.arity)
assert_equal([[:req, :b]], m.parameters)

m = A.instance_method(:a)
assert_equal(1, m.arity)
assert_equal([[:req, :b]], m.parameters)
end;
end

def test_instance_methods
bug8881 = '[ruby-core:57080] [Bug #8881]'
assert_not_include(Foo.instance_methods(false), :z, bug8881)
Expand Down
6 changes: 3 additions & 3 deletions vm_method.c
Original file line number Diff line number Diff line change
Expand Up @@ -1370,8 +1370,8 @@ check_override_opt_method(VALUE klass, VALUE mid)
}
}

static VALUE
zsuper_to_super(int argc, VALUE *argv, VALUE self)
VALUE
rb_zsuper_to_super(int argc, VALUE *argv, VALUE self)
{
return rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
}
Expand Down Expand Up @@ -1486,7 +1486,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil
def = rb_method_definition_create(type, original_id);
if (turn_zsuper_to_super) {
def->type = VM_METHOD_TYPE_CFUNC;
def->body.cfunc.func = (rb_cfunc_t)zsuper_to_super;
def->body.cfunc.func = (rb_cfunc_t)rb_zsuper_to_super;
def->body.cfunc.invoker = ractor_safe_call_cfunc_m1;
def->body.cfunc.argc = -1;
}
Expand Down
2 changes: 1 addition & 1 deletion zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def stats_string
:gc_time_ns,
:invalidation_time_ns,

:vm_write_pc_count,
:vm_write_jit_frame_count,
:vm_write_sp_count,
:vm_write_locals_count,
:vm_write_stack_count,
Expand Down
4 changes: 2 additions & 2 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2708,8 +2708,8 @@ fn gen_save_pc_for_gc(asm: &mut Assembler, state: &FrameState) {
let opcode: usize = state.get_opcode().try_into().unwrap();
let next_pc: *const VALUE = unsafe { state.pc.offset(insn_len(opcode) as isize) };

gen_incr_counter(asm, Counter::vm_write_pc_count);
asm_comment!(asm, "save PC to CFP");
gen_incr_counter(asm, Counter::vm_write_jit_frame_count);
asm_comment!(asm, "save JITFrame to CFP");
if let Some(pc) = PC_POISON {
asm.mov(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_PC), Opnd::const_ptr(pc));
}
Expand Down
4 changes: 2 additions & 2 deletions zjit/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2998,8 +2998,8 @@ impl Function {
Insn::GetEP { .. } => types::CPtr,
Insn::LoadSelf => types::BasicObject,
&Insn::LoadField { return_type, .. } => return_type,
Insn::GetSpecialSymbol { .. } => types::BasicObject,
Insn::GetSpecialNumber { .. } => types::BasicObject,
Insn::GetSpecialSymbol { .. } => types::StringExact.union(types::NilClass),
Insn::GetSpecialNumber { .. } => types::StringExact.union(types::NilClass),
Insn::GetClassVar { .. } => types::BasicObject,
Insn::ToNewArray { .. } => types::ArrayExact,
Insn::ToArray { .. } => types::ArrayExact,
Expand Down
8 changes: 7 additions & 1 deletion zjit/src/hir/opt_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11109,7 +11109,7 @@ mod hir_opt_tests {
}

#[test]
fn test_dont_inline_integer_xor_with_bignum_or_boolean() {
fn test_dont_inline_integer_xor_with_bignum_lhs() {
eval("
def test(x, y) = x ^ y
test(4 << 70, 1)
Expand All @@ -11136,7 +11136,10 @@ mod hir_opt_tests {
CheckInterrupts
Return v28
");
}

#[test]
fn test_dont_inline_integer_xor_with_bignum_rhs() {
eval("
def test(x, y) = x ^ y
test(1, 4 << 70)
Expand All @@ -11163,7 +11166,10 @@ mod hir_opt_tests {
CheckInterrupts
Return v28
");
}

#[test]
fn test_dont_inline_integer_xor_with_boolean() {
eval("
def test(x, y) = x ^ y
test(true, 0)
Expand Down
60 changes: 60 additions & 0 deletions zjit/src/hir/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5525,6 +5525,66 @@ pub(crate) mod hir_build_tests {
assert!(hir.contains("BreakPoint"));
assert!(hir.contains("Return v"));
}

#[test]
fn test_getspecialnumber() {
eval("
def test(a)
a =~/(hello)/
$1
end
");
assert_snapshot!(hir_string("test"), @"
fn test@<compiled>:3:
bb1():
EntryPoint interpreter
v1:BasicObject = LoadSelf
v2:CPtr = LoadSP
v3:BasicObject = LoadField v2, :a@0x1000
Jump bb3(v1, v3)
bb2():
EntryPoint JIT(0)
v6:BasicObject = LoadArg :self@0
v7:BasicObject = LoadArg :a@1
Jump bb3(v6, v7)
bb3(v9:BasicObject, v10:BasicObject):
v15:RegexpExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v18:BasicObject = Send v10, :=~, v15 # SendFallbackReason: Uncategorized(opt_regexpmatch2)
v22:StringExact|NilClass = GetSpecialNumber 2
CheckInterrupts
Return v22
");
}

#[test]
fn test_getspecialsymbol() {
eval("
def test(a)
a =~/(hello)/
$&
end
");
assert_snapshot!(hir_string("test"), @"
fn test@<compiled>:3:
bb1():
EntryPoint interpreter
v1:BasicObject = LoadSelf
v2:CPtr = LoadSP
v3:BasicObject = LoadField v2, :a@0x1000
Jump bb3(v1, v3)
bb2():
EntryPoint JIT(0)
v6:BasicObject = LoadArg :self@0
v7:BasicObject = LoadArg :a@1
Jump bb3(v6, v7)
bb3(v9:BasicObject, v10:BasicObject):
v15:RegexpExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v18:BasicObject = Send v10, :=~, v15 # SendFallbackReason: Uncategorized(opt_regexpmatch2)
v22:StringExact|NilClass = GetSpecialSymbol LastMatch
CheckInterrupts
Return v22
");
}
}

/// Test successor and predecessor set computations.
Expand Down
2 changes: 1 addition & 1 deletion zjit/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ make_counters! {
complex_arg_pass_caller_forwarding,

// Writes to the VM frame
vm_write_pc_count,
vm_write_jit_frame_count,
vm_write_sp_count,
vm_write_locals_count,
vm_write_stack_count,
Expand Down