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
50 changes: 50 additions & 0 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,56 @@ jobs:

steps: *make-steps

# Separated from `make` job to avoid making it a required status check
ruby-bench:
strategy:
matrix:
include:
# Using the same setup as ZJIT jobs
- bench_opts: '--warmup=1 --bench=1'

runs-on: ubuntu-24.04

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@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

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

- 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"

- run: make install

- name: Checkout ruby-bench
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
repository: ruby/ruby-bench
path: ruby-bench

- name: Run ruby-bench
run: ruby run_benchmarks.rb -e "ruby::../build/install/bin/ruby" ${{ 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() }}

result:
if: ${{ always() }}
name: ${{ github.workflow }} result
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
include:
# Test --call-threshold=2 with 2 iterations in total
- ruby_opts: '--zjit-call-threshold=2'
bench_opts: '--warmup=1 --bench=1'
bench_opts: '--warmup=1 --bench=1 --excludes=fluentd,psych-load,railsbench'
configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow

runs-on: macos-14
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/zjit-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ jobs:
include:
# Test --call-threshold=2 with 2 iterations in total
- ruby_opts: '--zjit-call-threshold=2'
bench_opts: '--warmup=1 --bench=1'
bench_opts: '--warmup=1 --bench=1 --excludes=fluentd,psych-load,railsbench'
configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow

runs-on: ubuntu-24.04
Expand Down
12 changes: 6 additions & 6 deletions encoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ enc_check_encoding(VALUE obj)
if (!is_obj_encoding(obj)) {
return -1;
}
return check_encoding(RDATA(obj)->data);
return check_encoding(RTYPEDDATA_GET_DATA(obj));
}

NORETURN(static void not_encoding(VALUE enc));
Expand All @@ -240,7 +240,7 @@ must_encoding(VALUE enc)
if (index < 0) {
not_encoding(enc);
}
return DATA_PTR(enc);
return RTYPEDDATA_GET_DATA(enc);
}

static rb_encoding *
Expand Down Expand Up @@ -328,15 +328,15 @@ str_to_encoding(VALUE enc)
rb_encoding *
rb_to_encoding(VALUE enc)
{
if (enc_check_encoding(enc) >= 0) return RDATA(enc)->data;
if (enc_check_encoding(enc) >= 0) return RTYPEDDATA_GET_DATA(enc);
return str_to_encoding(enc);
}

rb_encoding *
rb_find_encoding(VALUE enc)
{
int idx;
if (enc_check_encoding(enc) >= 0) return RDATA(enc)->data;
if (enc_check_encoding(enc) >= 0) return RTYPEDDATA_GET_DATA(enc);
idx = str_find_encindex(enc);
if (idx < 0) return NULL;
return rb_enc_from_index(idx);
Expand Down Expand Up @@ -1345,7 +1345,7 @@ enc_inspect(VALUE self)
if (!is_data_encoding(self)) {
not_encoding(self);
}
if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
if (!(enc = RTYPEDDATA_GET_DATA(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
rb_raise(rb_eTypeError, "broken Encoding");
}

Expand All @@ -1368,7 +1368,7 @@ enc_inspect(VALUE self)
static VALUE
enc_name(VALUE self)
{
return rb_fstring_cstr(rb_enc_name((rb_encoding*)DATA_PTR(self)));
return rb_fstring_cstr(rb_enc_name((rb_encoding*)RTYPEDDATA_GET_DATA(self)));
}

static int
Expand Down
4 changes: 2 additions & 2 deletions ext/-test-/string/fstring.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ bug_s_fstring_fake_str(VALUE self)
VALUE
bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
{
return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
}

VALUE
bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
{
return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
}

void
Expand Down
4 changes: 2 additions & 2 deletions zjit/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3155,8 +3155,6 @@ impl Function {
// We're only looking at T_OBJECT so ignore all of the imemo stuff.
assert!(recv_type.flags().is_t_object());
next_shape_id = ShapeId(unsafe { rb_shape_transition_add_ivar_no_warnings(class, current_shape_id.0, id) });
let ivar_result = unsafe { rb_shape_get_iv_index(next_shape_id.0, id, &mut ivar_index) };
assert!(ivar_result, "New shape must have the ivar index");
// If the VM ran out of shapes, or this class generated too many leaf,
// it may be de-optimized into OBJ_TOO_COMPLEX_SHAPE (hash-table).
let new_shape_too_complex = unsafe { rb_jit_shape_too_complex_p(next_shape_id.0) };
Expand All @@ -3165,6 +3163,8 @@ impl Function {
self.push_insn(block, Insn::IncrCounter(Counter::setivar_fallback_new_shape_too_complex));
self.push_insn_id(block, insn_id); continue;
}
let ivar_result = unsafe { rb_shape_get_iv_index(next_shape_id.0, id, &mut ivar_index) };
assert!(ivar_result, "New shape must have the ivar index");
let current_capacity = unsafe { rb_jit_shape_capacity(current_shape_id.0) };
let next_capacity = unsafe { rb_jit_shape_capacity(next_shape_id.0) };
// If the new shape has a different capacity, or is TOO_COMPLEX, we'll have to
Expand Down
32 changes: 32 additions & 0 deletions zjit/src/hir/opt_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3932,6 +3932,38 @@ mod hir_opt_tests {
");
}

#[test]
fn test_dont_specialize_setivar_when_next_shape_is_too_complex() {
eval(r#"
class AboutToBeTooComplex
def test = @abc = 5
end
SHAPE_MAX_VARIATIONS = 8 # see shape.h
SHAPE_MAX_VARIATIONS.times do
AboutToBeTooComplex.new.instance_variable_set(:"@a#{_1}", 1)
end
AboutToBeTooComplex.new.test
TEST = AboutToBeTooComplex.instance_method(:test)
"#);
assert_snapshot!(hir_string_proc("TEST"), @r"
fn test@<compiled>:3:
bb0():
EntryPoint interpreter
v1:BasicObject = LoadSelf
Jump bb2(v1)
bb1(v4:BasicObject):
EntryPoint JIT(0)
Jump bb2(v4)
bb2(v6:BasicObject):
v10:Fixnum[5] = Const Value(5)
PatchPoint SingleRactorMode
IncrCounter setivar_fallback_new_shape_too_complex
SetIvar v6, :@abc, v10
CheckInterrupts
Return v10
");
}

#[test]
fn test_elide_freeze_with_frozen_hash() {
eval("
Expand Down