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
52 changes: 52 additions & 0 deletions .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,58 @@ jobs:
working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}

# Separated from `make` job to avoid making it a required status check for now
ruby-bench:
strategy:
matrix:
include:
# Test --call-threshold=2 with 2 iterations in total
- ruby_opts: '--zjit-call-threshold=2'
bench_opts: '--warmup=1 --bench=1'
configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow

runs-on: macos-14

if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
|| contains(github.event.pull_request.title, '[DOC]')
|| contains(github.event.pull_request.labels.*.name, 'Documentation')
|| (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- uses: ./.github/actions/setup/macos

- uses: ./.github/actions/setup/directories
with:
srcdir: src
builddir: build
makeup: true

- name: Run configure
run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }}

- run: make install

- name: Checkout ruby-bench
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: ruby/ruby-bench
path: ruby-bench

- name: Run ruby-bench
run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }}
working-directory: ruby-bench

- uses: ./.github/actions/slack
with:
label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}

defaults:
run:
working-directory: build
5 changes: 3 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,17 @@ The following bundled gems are added.
The following bundled gems are updated.

* minitest 5.26.0
* power_assert 3.0.0
* power_assert 3.0.1
* rake 13.3.1
* test-unit 3.7.0
* test-unit 3.7.1
* rexml 3.4.4
* net-ftp 0.3.9
* net-imap 0.5.12
* net-smtp 0.5.1
* matrix 0.4.3
* prime 0.1.4
* rbs 3.9.5
* typeprof 0.31.0
* debug 1.11.0
* base64 0.3.0
* bigdecimal 3.3.1
Expand Down
2 changes: 1 addition & 1 deletion bootstraptest/test_io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
ARGF.set_encoding "foo"
}

/freebsd/ =~ RUBY_PLATFORM or
/(freebsd|mswin)/ =~ RUBY_PLATFORM or
10.times do
assert_normal_exit %q{
at_exit { p :foo }
Expand Down
13 changes: 13 additions & 0 deletions bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,19 @@ def ==(o)
roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
}

# move object with generic ivars and existing id2ref table
# [Bug #21664]
assert_equal 'ok', %q{
obj = [1]
obj.instance_variable_set("@field", :ok)
ObjectSpace._id2ref(obj.object_id) # build id2ref table

ractor = Ractor.new { Ractor.receive }
ractor.send(obj, move: true)
obj = ractor.value
obj.instance_variable_get("@field")
}

# copy object with complex generic ivars
assert_equal 'ok', %q{
# Make Array too_complex
Expand Down
6 changes: 3 additions & 3 deletions gems/bundled_gems
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
# if `revision` is not given, "v"+`version` or `version` will be used.

minitest 5.26.0 https://github.com/minitest/minitest
power_assert 3.0.0 https://github.com/ruby/power_assert
power_assert 3.0.1 https://github.com/ruby/power_assert
rake 13.3.1 https://github.com/ruby/rake
test-unit 3.7.0 https://github.com/test-unit/test-unit
test-unit 3.7.1 https://github.com/test-unit/test-unit
rexml 3.4.4 https://github.com/ruby/rexml
rss 0.3.1 https://github.com/ruby/rss
net-ftp 0.3.9 https://github.com/ruby/net-ftp
Expand All @@ -19,7 +19,7 @@ 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.5 https://github.com/ruby/rbs
typeprof 0.30.1 https://github.com/ruby/typeprof
typeprof 0.31.0 https://github.com/ruby/typeprof
debug 1.11.0 https://github.com/ruby/debug
racc 1.8.1 https://github.com/ruby/racc
mutex_m 0.3.0 https://github.com/ruby/mutex_m
Expand Down
4 changes: 2 additions & 2 deletions lib/erb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
# \ERB supports tags of three kinds:
#
# - [Expression tags][expression tags]:
# each begins with `'<%'`, ends with `'%>'`; contains a Ruby expression;
# each begins with `'<%='`, ends with `'%>'`; contains a Ruby expression;
# in the result, the value of the expression replaces the entire tag:
#
# template = 'The magic word is <%= magic_word %>.'
Expand All @@ -77,7 +77,7 @@
# ERB.new('Today is <%= Date::DAYNAMES[Date.today.wday] %>.').result # => "Today is Monday."
#
# - [Execution tags][execution tags]:
# each begins with `'<%='`, ends with `'%>'`; contains Ruby code to be executed:
# each begins with `'<%'`, ends with `'%>'`; contains Ruby code to be executed:
#
# template = '<% File.write("t.txt", "Some stuff.") %>'
# ERB.new(template).result
Expand Down
5 changes: 2 additions & 3 deletions ractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1973,13 +1973,12 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data)
rb_gc_writebarrier_remember(data->replacement);

void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c

rb_gc_obj_id_moved(data->replacement);

if (UNLIKELY(rb_obj_exivar_p(obj))) {
rb_replace_generic_ivar(data->replacement, obj);
}

rb_gc_obj_id_moved(data->replacement);

VALUE flags = T_OBJECT | FL_FREEZE | (RBASIC(obj)->flags & FL_PROMOTED);

// Avoid mutations using bind_call, etc.
Expand Down
6 changes: 6 additions & 0 deletions test/ruby/test_autoload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -613,4 +613,10 @@ module SomeNamespace
RUBY
end
end

private

def assert_separately(*args, **kwargs)
super(*args, **{ timeout: 60 }.merge(kwargs))
end
end
2 changes: 1 addition & 1 deletion test/test_extlibs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def self.check_existence(ext, add_msg = nil)
add_msg = ". #{add_msg}" if add_msg
log = "#{@extdir}/#{ext}/mkmf.log"
define_method("test_existence_of_#{ext}") do
assert_separately([], <<-"end;", ignore_stderr: true) # do
assert_separately([], <<-"end;", ignore_stderr: true, timeout: 60) # do
log = #{log.dump}
msg = proc {
"extension library `#{ext}' is not found#{add_msg}\n" <<
Expand Down
8 changes: 7 additions & 1 deletion zjit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def stats_string
stats = self.stats

stats[:guard_type_exit_ratio] = stats[:exit_guard_type_failure].to_f / stats[:guard_type_count] * 100
stats[:guard_shape_exit_ratio] = stats[:exit_guard_shape_failure].to_f / stats[:guard_shape_count] * 100

# Show counters independent from exit_* or dynamic_send_*
print_counters_with_prefix(prefix: 'not_inlined_cfuncs_', prompt: 'not inlined C methods', buf:, stats:, limit: 20)
Expand Down Expand Up @@ -206,8 +207,13 @@ def stats_string

:guard_type_count,
:guard_type_exit_ratio,
:guard_shape_count,
:guard_shape_exit_ratio,

:code_region_bytes,
:zjit_alloc_bytes,
:total_mem_bytes,

:side_exit_count,
:total_insn_count,
:vm_insn_count,
Expand Down Expand Up @@ -242,7 +248,7 @@ def print_counters(keys, buf:, stats:, right_align: false, base: nil)
case key
when :ratio_in_zjit
value = '%0.1f%%' % value
when :guard_type_exit_ratio
when :guard_type_exit_ratio, :guard_shape_exit_ratio
value = '%0.1f%%' % value
when /_time_ns\z/
key = key.to_s.sub(/_time_ns\z/, '_time')
Expand Down
1 change: 1 addition & 0 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,7 @@ fn gen_array_extend(jit: &mut JITState, asm: &mut Assembler, left: Opnd, right:
}

fn gen_guard_shape(jit: &mut JITState, asm: &mut Assembler, val: Opnd, shape: ShapeId, state: &FrameState) -> Opnd {
gen_incr_counter(asm, Counter::guard_shape_count);
let shape_id_offset = unsafe { rb_shape_id_offset() };
let val = asm.load(val);
let shape_opnd = Opnd::mem(SHAPE_ID_NUM_BITS as u8, val, shape_id_offset);
Expand Down
8 changes: 6 additions & 2 deletions zjit/src/stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ make_counters! {

// The number of times we ran a dynamic check
guard_type_count,
guard_shape_count,
}

/// Increase a counter by a specified amount
Expand Down Expand Up @@ -549,7 +550,10 @@ pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) ->
}

// Memory usage stats
set_stat_usize!(hash, "code_region_bytes", ZJITState::get_code_block().mapped_region_size());
let code_region_bytes = ZJITState::get_code_block().mapped_region_size();
set_stat_usize!(hash, "code_region_bytes", code_region_bytes);
set_stat_usize!(hash, "zjit_alloc_bytes", zjit_alloc_bytes());
set_stat_usize!(hash, "total_mem_bytes", code_region_bytes + zjit_alloc_bytes());

// End of default stats. Every counter beyond this is provided only for --zjit-stats.
if !get_option!(stats) {
Expand Down Expand Up @@ -644,7 +648,7 @@ pub fn with_time_stat<F, R>(counter: Counter, func: F) -> R where F: FnOnce() ->
}

/// The number of bytes ZJIT has allocated on the Rust heap.
pub fn zjit_alloc_size() -> usize {
pub fn zjit_alloc_bytes() -> usize {
jit::GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst)
}

Expand Down
4 changes: 2 additions & 2 deletions zjit/src/virtualmem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use std::ptr::NonNull;
use crate::cruby::*;
use crate::stats::zjit_alloc_size;
use crate::stats::zjit_alloc_bytes;

pub type VirtualMem = VirtualMemory<sys::SystemAllocator>;

Expand Down Expand Up @@ -199,7 +199,7 @@ impl<A: Allocator> VirtualMemory<A> {
// Ignore zjit_alloc_size() if self.memory_limit_bytes is None for testing
let mut required_region_bytes = page_addr + page_size - start as usize;
if self.memory_limit_bytes.is_some() {
required_region_bytes += zjit_alloc_size();
required_region_bytes += zjit_alloc_bytes();
}

assert!((start..=whole_region_end).contains(&mapped_region_end));
Expand Down