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
10 changes: 2 additions & 8 deletions .github/workflows/ubuntu-ibm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,8 @@ jobs:
- name: Run configure
env:
configure: ${{ matrix.configure }}
# Don't set cppflags=-DRUBY_DEBUG on ppc64le, due to some Ractor tests
# failing in the case.
# https://bugs.ruby-lang.org/issues/21534
run: |
if [ "$(uname -m)" != "ppc64le" ]; then
configure="${configure:-cppflags=-DRUBY_DEBUG}"
fi
../src/configure -C --disable-install-doc ${configure}
run: >-
../src/configure -C --disable-install-doc ${configure:-cppflags=-DRUBY_DEBUG}

- run: make

Expand Down
62 changes: 62 additions & 0 deletions test/ruby/test_zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,22 @@ def function_stub_exit(init)
}, call_threshold: 2, allowed_iseqs: 'entry@-e:2'
end

def test_send_optional_arguments
assert_compiles '[[1, 2], [3, 4]]', %q{
def test(a, b = 2) = [a, b]
def entry = [test(1), test(3, 4)]
entry
entry
}, call_threshold: 2
end

def test_iseq_with_optional_arguments
assert_compiles '[[1, 2], [3, 4]]', %q{
def test(a, b = 2) = [a, b]
[test(1), test(3, 4)]
}
end

def test_invokebuiltin
omit 'Test fails at the moment due to not handling optional parameters'
assert_compiles '["."]', %q{
Expand Down Expand Up @@ -2240,6 +2256,52 @@ def foo = 1
}
end

def test_line_tracepoint_on_c_method
assert_compiles '"[[:line, true]]"', %q{
events = []
events.instance_variable_set(
:@tp,
TracePoint.new(:line) { |tp| events << [tp.event, tp.lineno] if tp.path == __FILE__ }
)
def events.to_str
@tp.enable; ''
end

# Stay in generated code while enabling tracing
def events.compiled(obj)
String(obj)
@tp.disable; __LINE__
end

line = events.compiled(events)
events[0][-1] = (events[0][-1] == line)

events.to_s # can't dump events as it's a singleton object AND it has a TracePoint instance variable, which also can't be dumped
}
end

def test_targeted_line_tracepoint_in_c_method_call
assert_compiles '"[true]"', %q{
events = []
events.instance_variable_set(:@tp, TracePoint.new(:line) { |tp| events << tp.lineno })
def events.to_str
@tp.enable(target: method(:compiled))
''
end

# Stay in generated code while enabling tracing
def events.compiled(obj)
String(obj)
__LINE__
end

line = events.compiled(events)
events[0] = (events[0] == line)

events.to_s # can't dump events as it's a singleton object AND it has a TracePoint instance variable, which also can't be dumped
}
end

def test_opt_case_dispatch
assert_compiles '[true, false]', %q{
def test(x)
Expand Down
4 changes: 2 additions & 2 deletions thread_pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ struct rb_thread_sched {
#ifdef RB_THREAD_LOCAL_SPECIFIER
NOINLINE(void rb_current_ec_set(struct rb_execution_context_struct *));

# if defined(__arm64__) || defined(__aarch64__)
// on Arm64, TLS can not be accessed across .so
# if defined(__arm64__) || defined(__aarch64__) || defined(__powerpc64__)
// TLS can not be accessed across .so on arm64 and perhaps ppc64le too.
NOINLINE(struct rb_execution_context_struct *rb_current_ec(void));
# else
RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec;
Expand Down
2 changes: 1 addition & 1 deletion vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ rb_current_ec_set(rb_execution_context_t *ec)
}


#if defined(__arm64__) || defined(__aarch64__)
#if defined(__arm64__) || defined(__aarch64__) || defined(__powerpc64__)
rb_execution_context_t *
rb_current_ec(void)
{
Expand Down
2 changes: 1 addition & 1 deletion vm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2001,7 +2001,7 @@ static inline rb_execution_context_t *
rb_current_execution_context(bool expect_ec)
{
#ifdef RB_THREAD_LOCAL_SPECIFIER
#if defined(__arm64__) || defined(__aarch64__)
#if defined(__arm64__) || defined(__aarch64__) || defined(__powerpc64__)
rb_execution_context_t * volatile ec = rb_current_ec();
#else
rb_execution_context_t * volatile ec = ruby_current_ec;
Expand Down
1 change: 1 addition & 0 deletions zjit/bindgen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ fn main() {
.allowlist_type("vm_check_match_type")
.allowlist_type("vm_opt_newarray_send_type")
.allowlist_type("rb_iseq_type")
.allowlist_type("rb_event_flag_t")

// From zjit.c
.allowlist_function("rb_object_shape_count")
Expand Down
26 changes: 23 additions & 3 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use std::slice;

use crate::asm::Label;
use crate::backend::current::{Reg, ALLOC_REGS};
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption};
use crate::invariants::{track_bop_assumption, track_cme_assumption, track_single_ractor_assumption, track_stable_constant_names_assumption, track_no_trace_point_assumption};
use crate::gc::{append_gc_offsets, get_or_create_iseq_payload, get_or_create_iseq_payload_ptr, IseqPayload, IseqStatus};
use crate::state::ZJITState;
use crate::stats::{exit_counter_for_compile_error, incr_counter, incr_counter_by, CompileError};
use crate::stats::{counter_ptr, with_time_stat, Counter, Counter::{compile_time_ns, exit_compile_error}};
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
use crate::backend::lir::{self, asm_comment, asm_ccall, Assembler, Opnd, Target, CFP, C_ARG_OPNDS, C_RET_OPND, EC, NATIVE_STACK_PTR, NATIVE_BASE_PTR, SCRATCH_OPND, SP};
use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, Invariant, RangeType, SideExitReason, SideExitReason::*, SpecialObjectType, SpecialBackrefSymbol, SELF_PARAM_IDX};
use crate::hir::{Const, FrameState, Function, Insn, InsnId, ParseError};
use crate::hir::{Const, FrameState, Function, Insn, InsnId};
use crate::hir_type::{types, Type};
use crate::options::get_option;

Expand Down Expand Up @@ -593,6 +593,10 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
let side_exit_ptr = cb.resolve_label(label);
track_stable_constant_names_assumption(idlist, code_ptr, side_exit_ptr, payload_ptr);
}
Invariant::NoTracePoint => {
let side_exit_ptr = cb.resolve_label(label);
track_no_trace_point_assumption(code_ptr, side_exit_ptr, payload_ptr);
}
Invariant::SingleRactorMode => {
let side_exit_ptr = cb.resolve_label(label);
track_single_ractor_assumption(code_ptr, side_exit_ptr, payload_ptr);
Expand Down Expand Up @@ -770,7 +774,22 @@ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) {
// Load the current SP from the CFP into REG_SP
asm.mov(SP, Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SP));

// TODO: Support entry chain guard when ISEQ has_opt
// Currently, we support only the case that no optional arguments are given.
// Bail out if any optional argument is supplied.
let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) };
if opt_num > 0 {
asm_comment!(asm, "guard no optional arguments");
let no_opts_pc = unsafe { rb_iseq_pc_at_idx(iseq, 0) };
asm.cmp(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_PC), Opnd::const_ptr(no_opts_pc));
let no_opts_label = asm.new_label("no_opts");
asm.je(no_opts_label.clone());

gen_incr_counter(asm, Counter::exit_optional_arguments);
asm.frame_teardown(lir::JIT_PRESERVED_REGS);
asm.cret(Qundef.into());

asm.write_label(no_opts_label);
}
}

/// Assign method arguments to basic block arguments at JIT entry
Expand Down Expand Up @@ -1512,6 +1531,7 @@ fn compile_iseq(iseq: IseqPtr) -> Result<Function, CompileError> {
#[cfg(debug_assertions)]
if let Err(err) = function.validate() {
debug!("ZJIT: compile_iseq: {err:?}");
use crate::hir::ParseError;
return Err(CompileError::ParseError(ParseError::Validation(err)));
}
Ok(function)
Expand Down
1 change: 1 addition & 0 deletions zjit/src/cruby_bindings.inc.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading