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
5 changes: 3 additions & 2 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ jobs:
- test_task: test-bundled-gems
- test_task: check
os: ubuntu-24.04
- test_task: check
os: ubuntu-24.04-arm
# ubuntu-24.04-arm jobs don't start on ruby/ruby as of 2025-09-04
#- test_task: check
# os: ubuntu-24.04-arm
fail-fast: false

env:
Expand Down
43 changes: 2 additions & 41 deletions .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ jobs:
configure: '--enable-zjit=dev'
testopts: '--seed=11831'

- test_task: 'btest'
- test_task: 'test'
configure: '--enable-zjit=dev'
zjit_opts: '--zjit-call-threshold=1'

env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
Expand Down Expand Up @@ -106,45 +107,6 @@ jobs:
ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
if: ${{ contains(matrix.configure, 'jit=dev') }}

- name: btest
run: |
RUST_BACKTRACE=1 ruby --disable=gems ../src/bootstraptest/runner.rb --ruby="./miniruby -I../src/lib -I. -I.ext/common --zjit-call-threshold=1" \
../src/bootstraptest/test_attr.rb \
../src/bootstraptest/test_autoload.rb \
../src/bootstraptest/test_block.rb \
../src/bootstraptest/test_class.rb \
../src/bootstraptest/test_constant_cache.rb \
../src/bootstraptest/test_env.rb \
../src/bootstraptest/test_eval.rb \
../src/bootstraptest/test_exception.rb \
../src/bootstraptest/test_fiber.rb \
../src/bootstraptest/test_finalizer.rb \
../src/bootstraptest/test_flip.rb \
../src/bootstraptest/test_flow.rb \
../src/bootstraptest/test_fork.rb \
../src/bootstraptest/test_gc.rb \
../src/bootstraptest/test_insns.rb \
../src/bootstraptest/test_io.rb \
../src/bootstraptest/test_jump.rb \
../src/bootstraptest/test_literal.rb \
../src/bootstraptest/test_literal_suffix.rb \
../src/bootstraptest/test_load.rb \
../src/bootstraptest/test_marshal.rb \
../src/bootstraptest/test_massign.rb \
../src/bootstraptest/test_method.rb \
../src/bootstraptest/test_objectspace.rb \
../src/bootstraptest/test_proc.rb \
../src/bootstraptest/test_ractor.rb \
../src/bootstraptest/test_string.rb \
../src/bootstraptest/test_struct.rb \
../src/bootstraptest/test_syntax.rb \
../src/bootstraptest/test_thread.rb \
../src/bootstraptest/test_yjit_30k_ifelse.rb \
../src/bootstraptest/test_yjit_30k_methods.rb \
../src/bootstraptest/test_yjit_rust_port.rb
# ../src/bootstraptest/test_yjit.rb \
if: ${{ matrix.test_task == 'btest' }}

- name: make ${{ matrix.test_task }}
run: >-
make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
Expand All @@ -159,7 +121,6 @@ jobs:
PRECHECK_BUNDLED_GEMS: 'no'
TESTS: ${{ matrix.tests }}
continue-on-error: ${{ matrix.continue-on-test_task || false }}
if: ${{ matrix.test_task != 'btest' }}

result:
if: ${{ always() }}
Expand Down
43 changes: 2 additions & 41 deletions .github/workflows/zjit-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ jobs:
configure: '--enable-zjit=dev'
testopts: '--seed=18140'

- test_task: 'btest'
- test_task: 'test'
configure: '--enable-zjit=dev'
zjit_opts: '--zjit-call-threshold=1'

env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
Expand Down Expand Up @@ -147,45 +148,6 @@ jobs:
run: ./miniruby --zjit -v | grep "+ZJIT"
if: ${{ matrix.configure != '--disable-zjit' }}

- name: btest
run: |
RUST_BACKTRACE=1 ruby --disable=gems ../src/bootstraptest/runner.rb --ruby="./miniruby -I../src/lib -I. -I.ext/common --zjit-call-threshold=1" \
../src/bootstraptest/test_attr.rb \
../src/bootstraptest/test_autoload.rb \
../src/bootstraptest/test_block.rb \
../src/bootstraptest/test_class.rb \
../src/bootstraptest/test_constant_cache.rb \
../src/bootstraptest/test_env.rb \
../src/bootstraptest/test_env.rb \
../src/bootstraptest/test_exception.rb \
../src/bootstraptest/test_fiber.rb \
../src/bootstraptest/test_finalizer.rb \
../src/bootstraptest/test_flip.rb \
../src/bootstraptest/test_flow.rb \
../src/bootstraptest/test_fork.rb \
../src/bootstraptest/test_gc.rb \
../src/bootstraptest/test_insns.rb \
../src/bootstraptest/test_io.rb \
../src/bootstraptest/test_jump.rb \
../src/bootstraptest/test_literal.rb \
../src/bootstraptest/test_literal_suffix.rb \
../src/bootstraptest/test_load.rb \
../src/bootstraptest/test_marshal.rb \
../src/bootstraptest/test_massign.rb \
../src/bootstraptest/test_method.rb \
../src/bootstraptest/test_objectspace.rb \
../src/bootstraptest/test_proc.rb \
../src/bootstraptest/test_ractor.rb \
../src/bootstraptest/test_string.rb \
../src/bootstraptest/test_struct.rb \
../src/bootstraptest/test_syntax.rb \
../src/bootstraptest/test_thread.rb \
../src/bootstraptest/test_yjit_30k_ifelse.rb \
../src/bootstraptest/test_yjit_30k_methods.rb \
../src/bootstraptest/test_yjit_rust_port.rb
# ../src/bootstraptest/test_yjit.rb \
if: ${{ matrix.test_task == 'btest' }}

- name: make ${{ matrix.test_task }}
run: >-
make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
Expand All @@ -202,7 +164,6 @@ jobs:
LIBCLANG_PATH: ${{ matrix.libclang_path }}
TESTS: ${{ matrix.tests }}
continue-on-error: ${{ matrix.continue-on-test_task || false }}
if: ${{ matrix.test_task != 'btest' }}

result:
if: ${{ always() }}
Expand Down
2 changes: 1 addition & 1 deletion spec/ruby/command_line/feature_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
env = {'RUBYOPT' => '-w'}
# Use a single variant here because it can be quite slow as it might enable jit, etc
ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
end
end unless defined?(RubyVM::YJIT) && defined?(RubyVM::ZJIT) && RubyVM::ZJIT.enabled? # You're not supposed to enable YJIT with --enable-all when ZJIT options are passed.
end

it "can be used with all for disable" do
Expand Down
4 changes: 2 additions & 2 deletions spec/ruby/command_line/rubyopt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
ruby_exe("")[/\A.*/].gsub(/\s\+(PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(PRISM|GC(\[\w+\])?)(?=\s)/, "")
ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end

it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
ruby_exe("")[/\A.*/].gsub(/\s\+(PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(PRISM|GC(\[\w+\])?)(?=\s)/, "")
ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
end

Expand Down
42 changes: 41 additions & 1 deletion test/ruby/test_zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ def test_nested_local_access
}, call_threshold: 3, insns: [:getlocal, :setlocal, :getlocal_WC_0, :setlocal_WC_1]
end

def test_read_local_written_by_children_iseqs
def test_send_with_local_written_by_blockiseq
assert_compiles '[1, 2]', %q{
def test
l1 = nil
Expand Down Expand Up @@ -343,6 +343,46 @@ def test(a, b = 2) = [a, b]
}
end

def test_invokesuper
assert_compiles '[6, 60]', %q{
class Foo
def foo(a) = a + 1
def bar(a) = a + 10
end

class Bar < Foo
def foo(a) = super(a) + 2
def bar(a) = super + 20
end

bar = Bar.new
[bar.foo(3), bar.bar(30)]
}
end

def test_invokesuper_with_local_written_by_blockiseq
# Using `assert_runs` because we don't compile invokeblock yet
assert_runs '3', %q{
class Foo
def test
yield
end
end

class Bar < Foo
def test
a = 1
super do
a += 2
end
a
end
end

Bar.new.test
}
end

def test_invokebuiltin
omit 'Test fails at the moment due to not handling optional parameters'
assert_compiles '["."]', %q{
Expand Down
27 changes: 0 additions & 27 deletions tool/ruby_vm/views/_insn_sp_pc_dependency.erb

This file was deleted.

33 changes: 33 additions & 0 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
Insn::SendWithoutBlockDirect { cd, state, args, .. } if args.len() + 1 > C_ARG_OPNDS.len() => // +1 for self
gen_send_without_block(jit, asm, *cd, &function.frame_state(*state)),
Insn::SendWithoutBlockDirect { cme, iseq, self_val, args, state, .. } => gen_send_without_block_direct(cb, jit, asm, *cme, *iseq, opnd!(self_val), opnds!(args), &function.frame_state(*state)),
&Insn::InvokeSuper { cd, blockiseq, state, .. } => gen_invokesuper(jit, asm, cd, blockiseq, &function.frame_state(state)),
// Ensure we have enough room fit ec, self, and arguments
// TODO remove this check when we have stack args (we can use Time.new to test it)
Insn::InvokeBuiltin { bf, state, .. } if bf.argc + 2 > (C_ARG_OPNDS.len() as i32) => return Err(*state),
Expand Down Expand Up @@ -1076,6 +1077,38 @@ fn gen_send_without_block_direct(
ret
}

/// Compile a dynamic dispatch for `super`
fn gen_invokesuper(
jit: &mut JITState,
asm: &mut Assembler,
cd: *const rb_call_data,
blockiseq: IseqPtr,
state: &FrameState,
) -> lir::Opnd {
gen_incr_counter(asm, Counter::dynamic_send_count);

// Save PC and SP
gen_prepare_call_with_gc(asm, state);
gen_save_sp(asm, state.stack().len());

// Spill locals and stack
gen_spill_locals(jit, asm, state);
gen_spill_stack(jit, asm, state);

asm_comment!(asm, "call super with dynamic dispatch");
unsafe extern "C" {
fn rb_vm_invokesuper(ec: EcPtr, cfp: CfpPtr, cd: VALUE, blockiseq: IseqPtr) -> VALUE;
}
let ret = asm.ccall(
rb_vm_invokesuper as *const u8,
vec![EC, CFP, (cd as usize).into(), VALUE(blockiseq as usize).into()],
);
// TODO: Add a PatchPoint here that can side-exit the function if the callee messed with
// the frame's locals

ret
}

/// Compile a string resurrection
fn gen_string_copy(asm: &mut Assembler, recv: Opnd, chilled: bool, state: &FrameState) -> Opnd {
// TODO: split rb_ec_str_resurrect into separate functions
Expand Down
Loading