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 bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def test n
end

3.times.map{Ractor.receive}.tally
} unless yjit_enabled? || zjit_enabled? # YJIT: `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec(), ZJIT hangs
} unless yjit_enabled? # YJIT: `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec()

# unshareable object are copied
assert_equal 'false', %q{
Expand Down
29 changes: 21 additions & 8 deletions gc/default/default.c
Original file line number Diff line number Diff line change
Expand Up @@ -4388,6 +4388,25 @@ gc_grey(rb_objspace_t *objspace, VALUE obj)
push_mark_stack(&objspace->mark_stack, obj);
}

static inline void
gc_mark_check_t_none(rb_objspace_t *objspace, VALUE obj)
{
if (RB_UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
char obj_info_buf[256];
rb_raw_obj_info(obj_info_buf, 256, obj);

char parent_obj_info_buf[256];
if (objspace->rgengc.parent_object == Qfalse) {
strcpy(parent_obj_info_buf, "(none)");
}
else {
rb_raw_obj_info(parent_obj_info_buf, 256, objspace->rgengc.parent_object);
}

rb_bug("try to mark T_NONE object (obj: %s, parent: %s)", obj_info_buf, parent_obj_info_buf);
}
}

static void
gc_mark(rb_objspace_t *objspace, VALUE obj)
{
Expand All @@ -4407,10 +4426,7 @@ gc_mark(rb_objspace_t *objspace, VALUE obj)
}
}

if (RB_UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
rb_obj_info_dump(obj);
rb_bug("try to mark T_NONE object"); /* check here will help debugging */
}
gc_mark_check_t_none(objspace, obj);

gc_aging(objspace, obj);
gc_grey(objspace, obj);
Expand Down Expand Up @@ -4504,10 +4520,7 @@ rb_gc_impl_mark_weak(void *objspace_ptr, VALUE *ptr)

VALUE obj = *ptr;

if (RB_UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
rb_obj_info_dump(obj);
rb_bug("try to mark T_NONE object");
}
gc_mark_check_t_none(objspace, obj);

/* If we are in a minor GC and the other object is old, then obj should
* already be marked and cannot be reclaimed in this GC cycle so we don't
Expand Down
2 changes: 1 addition & 1 deletion gc/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ RUBY_SYMBOL_EXPORT_BEGIN
// files in Ruby.
size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
void rb_obj_info_dump(VALUE obj);
const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
const char *rb_obj_info(VALUE obj);
size_t rb_obj_memsize_of(VALUE obj);
bool ruby_free_at_exit_p(void);
Expand Down
2 changes: 1 addition & 1 deletion gems/bundled_gems
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ net-pop 0.1.2 https://github.com/ruby/net-pop
net-smtp 0.5.1 https://github.com/ruby/net-smtp
matrix 0.4.3 https://github.com/ruby/matrix
prime 0.1.4 https://github.com/ruby/prime
rbs 3.9.4 https://github.com/ruby/rbs 368bf4b1ab52a9335e2022618ac4545a4d9cacdf
rbs 3.9.4 https://github.com/ruby/rbs aa22d7ea0c992de7557c3e346c9100b8aa36d945
typeprof 0.30.1 https://github.com/ruby/typeprof
debug 1.11.0 https://github.com/ruby/debug
racc 1.8.1 https://github.com/ruby/racc
Expand Down
2 changes: 1 addition & 1 deletion test/ruby/test_thread_cv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_condvar_wait_and_broadcast
condvar.broadcast
result << "P2"
end
Timeout.timeout(5) do
Timeout.timeout(60) do
nr_threads.times do |i|
threads[i].join
end
Expand Down
4 changes: 2 additions & 2 deletions test/ruby/test_transcode.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2321,7 +2321,7 @@ def test_newline_options
end

def test_ractor_lazy_load_encoding
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}")
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}", timeout: 60)
begin;
rs = []
autoload_encodings = Encoding.list.select { |e| e.inspect.include?("(autoload)") }.freeze
Expand Down Expand Up @@ -2385,7 +2385,7 @@ def test_ractor_asciicompat_encoding_exists
end

def test_ractor_asciicompat_encoding_doesnt_exist
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}")
assert_ractor("#{<<~"begin;"}\n#{<<~'end;'}", timeout: 60)
begin;
rs = []
NO_EXIST = "I".freeze
Expand Down
54 changes: 54 additions & 0 deletions test/ruby/test_zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,60 @@ def test(n) = n..10
}
end

def test_new_range_fixnum_both_literals_inclusive
assert_compiles '1..2', %q{
def test()
(1..2)
end
test; test
}, call_threshold: 2
end

def test_new_range_fixnum_both_literals_exclusive
assert_compiles '1...2', %q{
def test()
(1...2)
end
test; test
}, call_threshold: 2
end

def test_new_range_fixnum_low_literal_inclusive
assert_compiles '1..3', %q{
def test(a)
(1..a)
end
test(2); test(3)
}, call_threshold: 2
end

def test_new_range_fixnum_low_literal_exclusive
assert_compiles '1...3', %q{
def test(a)
(1...a)
end
test(2); test(3)
}, call_threshold: 2
end

def test_new_range_fixnum_high_literal_inclusive
assert_compiles '3..10', %q{
def test(a)
(a..10)
end
test(2); test(3)
}, call_threshold: 2
end

def test_new_range_fixnum_high_literal_exclusive
assert_compiles '3...10', %q{
def test(a)
(a...10)
end
test(2); test(3)
}, call_threshold: 2
end

def test_if
assert_compiles '[0, nil]', %q{
def test(n)
Expand Down
7 changes: 5 additions & 2 deletions test/socket/test_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,11 @@ def random_port

def errors_addrinuse
errs = [Errno::EADDRINUSE]
# MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721"
errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM
# Windows can fail with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721"
# or "Test::Unit::ProxyError: Permission denied - bind(2) for 0.0.0.0:55333"
if /mswin|mingw/ =~ RUBY_PLATFORM
errs += [Errno::EACCES, Test::Unit::ProxyError]
end
errs
end

Expand Down
11 changes: 7 additions & 4 deletions zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,18 @@ def stats_string
buf = +"***ZJIT: Printing ZJIT statistics on exit***\n"
stats = self.stats

print_counters_with_prefix(prefix: 'failed_', prompt: 'compilation failure reasons', buf:, stats:)
# Show exit reasons, ordered by the typical amount of exits for the prefix at the time
print_counters_with_prefix(prefix: 'unhandled_call_', prompt: 'unhandled call types', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'compile_error_', prompt: 'compile error reasons', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'exit_', prompt: 'side exit reasons', buf:, stats:, limit: 20)

# Show the most important stats ratio_in_zjit at the end
print_counters([
:dynamic_send_count,

:compiled_iseq_count,
:compilation_failure,
:failed_iseq_count,

:compile_time_ns,
:profile_time_ns,
Expand All @@ -54,8 +59,6 @@ def stats_string
:zjit_insn_count,
:ratio_in_zjit,
], buf:, stats:)
print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20)
print_counters_with_prefix(prefix: 'exit_', prompt: 'side exit reasons', buf:, stats:, limit: 20)

buf
end
Expand Down
10 changes: 5 additions & 5 deletions zjit/src/backend/arm64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::asm::{CodeBlock, Label};
use crate::asm::arm64::*;
use crate::cruby::*;
use crate::backend::lir::*;
use crate::stats::CompileError;
use crate::virtualmem::CodePtr;
use crate::cast::*;

Expand Down Expand Up @@ -1369,7 +1370,7 @@ impl Assembler
}

/// Optimize and compile the stored instructions
pub fn compile_with_regs(self, cb: &mut CodeBlock, regs: Vec<Reg>) -> Option<(CodePtr, Vec<CodePtr>)> {
pub fn compile_with_regs(self, cb: &mut CodeBlock, regs: Vec<Reg>) -> Result<(CodePtr, Vec<CodePtr>), CompileError> {
let asm = self.arm64_split();
let mut asm = asm.alloc_regs(regs)?;
asm.compile_side_exits();
Expand All @@ -1389,11 +1390,10 @@ impl Assembler
// Invalidate icache for newly written out region so we don't run stale code.
unsafe { rb_zjit_icache_invalidate(start_ptr.raw_ptr(cb) as _, cb.get_write_ptr().raw_ptr(cb) as _) };

Some((start_ptr, gc_offsets))
Ok((start_ptr, gc_offsets))
} else {
cb.clear_labels();

None
Err(CompileError::OutOfMemory)
}
}
}
Expand Down Expand Up @@ -1521,7 +1521,7 @@ mod tests {

let opnd = asm.add(Opnd::Reg(X0_REG), Opnd::Reg(X1_REG));
asm.store(Opnd::mem(64, Opnd::Reg(X2_REG), 0), opnd);
asm.compile_with_regs(&mut cb, vec![X3_REG]);
asm.compile_with_regs(&mut cb, vec![X3_REG]).unwrap();

// Assert that only 2 instructions were written.
assert_eq!(8, cb.get_write_pos());
Expand Down
12 changes: 6 additions & 6 deletions zjit/src/backend/lir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::cruby::{Qundef, RUBY_OFFSET_CFP_PC, RUBY_OFFSET_CFP_SP, SIZEOF_VALUE_
use crate::hir::SideExitReason;
use crate::options::{debug, get_option};
use crate::cruby::VALUE;
use crate::stats::{exit_counter_ptr, exit_counter_ptr_for_opcode, exit_counter_ptr_for_call_type};
use crate::stats::{exit_counter_ptr, exit_counter_ptr_for_call_type, exit_counter_ptr_for_opcode, CompileError};
use crate::virtualmem::CodePtr;
use crate::asm::{CodeBlock, Label};

Expand Down Expand Up @@ -1280,7 +1280,7 @@ impl Assembler
/// Sets the out field on the various instructions that require allocated
/// registers because their output is used as the operand on a subsequent
/// instruction. This is our implementation of the linear scan algorithm.
pub(super) fn alloc_regs(mut self, regs: Vec<Reg>) -> Option<Assembler> {
pub(super) fn alloc_regs(mut self, regs: Vec<Reg>) -> Result<Assembler, CompileError> {
// Dump live registers for register spill debugging.
fn dump_live_regs(insns: Vec<Insn>, live_ranges: Vec<LiveRange>, num_regs: usize, spill_index: usize) {
// Convert live_ranges to live_regs: the number of live registers at each index
Expand Down Expand Up @@ -1331,7 +1331,7 @@ impl Assembler
new_reg
} else {
debug!("spilling VReg is not implemented yet, can't evacuate C_RET_REG on CCall");
return None;
return Err(CompileError::RegisterSpillOnCCall);
};
asm.mov(Opnd::Reg(new_reg), C_RET_OPND);
pool.dealloc_reg(&C_RET_REG);
Expand Down Expand Up @@ -1436,7 +1436,7 @@ impl Assembler
dump_live_regs(insns, live_ranges, regs.len(), index);
}
debug!("Register spill not supported");
return None;
return Err(CompileError::RegisterSpillOnAlloc);
}
}
};
Expand Down Expand Up @@ -1522,13 +1522,13 @@ impl Assembler
}

assert!(pool.is_empty(), "Expected all registers to be returned to the pool");
Some(asm)
Ok(asm)
}

/// Compile the instructions down to machine code.
/// Can fail due to lack of code memory and inopportune code placement, among other reasons.
#[must_use]
pub fn compile(self, cb: &mut CodeBlock) -> Option<(CodePtr, Vec<CodePtr>)> {
pub fn compile(self, cb: &mut CodeBlock) -> Result<(CodePtr, Vec<CodePtr>), CompileError> {
#[cfg(feature = "disasm")]
let start_addr = cb.get_write_ptr();
let alloc_regs = Self::get_alloc_regs();
Expand Down
9 changes: 4 additions & 5 deletions zjit/src/backend/x86_64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::mem::take;

use crate::asm::*;
use crate::asm::x86_64::*;
use crate::stats::CompileError;
use crate::virtualmem::CodePtr;
use crate::cruby::*;
use crate::backend::lir::*;
Expand Down Expand Up @@ -892,7 +893,7 @@ impl Assembler
}

/// Optimize and compile the stored instructions
pub fn compile_with_regs(self, cb: &mut CodeBlock, regs: Vec<Reg>) -> Option<(CodePtr, Vec<CodePtr>)> {
pub fn compile_with_regs(self, cb: &mut CodeBlock, regs: Vec<Reg>) -> Result<(CodePtr, Vec<CodePtr>), CompileError> {
let asm = self.x86_split();
let mut asm = asm.alloc_regs(regs)?;
asm.compile_side_exits();
Expand All @@ -908,12 +909,10 @@ impl Assembler

if let (Some(gc_offsets), false) = (gc_offsets, cb.has_dropped_bytes()) {
cb.link_labels();

Some((start_ptr, gc_offsets))
Ok((start_ptr, gc_offsets))
} else {
cb.clear_labels();

None
Err(CompileError::OutOfMemory)
}
}
}
Expand Down
Loading