Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c42a633
ZJIT: Check native stack in function_stub_hit (#16585)
k0kubun Mar 27, 2026
324ba08
ZJIT: Categorize uncategorized send fallback reasons in stats
k0kubun Mar 27, 2026
6322acb
ZJIT: Set fallback reasons at HIR construction instead of type_specia…
k0kubun Mar 27, 2026
9a3fedd
[ruby/prism] Nodoc the ripper shim
Earlopain Mar 27, 2026
6519a77
ZJIT: Specialize invokeblock for IFUNC block handlers
k0kubun Mar 22, 2026
16e9610
ZJIT: Add tests for invokeblock IFUNC specialization
k0kubun Mar 27, 2026
cee3d5f
ZJIT: Combine two IFUNC tag guards into one
k0kubun Mar 27, 2026
2d2351a
Remove unused compile options/jobs (#16583)
Earlopain Mar 27, 2026
1b2dfdf
Fix crash report being truncated by secondary crashes (#16586)
k0kubun Mar 27, 2026
c8f9794
ZJIT: Lightweight Frames
k0kubun Feb 26, 2026
31dba12
ZJIT: Rename CFP_JIT_RETURN to CFP_HAS_JIT_RETURN
k0kubun Mar 26, 2026
9c7c28f
ZJIT: Simplify cfp accessor functions in zjit.h
k0kubun Mar 26, 2026
c5ed741
ZJIT: Add doc comments to JITFrame and split into two constructors
k0kubun Mar 26, 2026
984feb2
ZJIT: Import JITFrame directly instead of via payload
k0kubun Mar 26, 2026
219f7bb
ZJIT: Have JITFrame mark and update its own GC pointers
k0kubun Mar 26, 2026
59fe446
ZJIT: Use bare opcode variant in iseq_may_write_block_code
k0kubun Mar 27, 2026
29755f4
ZJIT: Move jit_return clearing from rb_set_cfp_pc into codegen
k0kubun Mar 27, 2026
bfcc31a
ZJIT: Define JITFrame struct in C and import via bindgen
k0kubun Mar 27, 2026
4e5b0d3
ZJIT: Have JITFrame relocate itself via Rust function
k0kubun Mar 27, 2026
226f370
Rename cfp->iseq to cfp->_iseq and rb_zjit_cfp_iseq to rb_cfp_iseq
k0kubun Mar 27, 2026
4391c5f
Use cfp->_iseq directly in GET_ISEQ() macro
k0kubun Mar 27, 2026
ee60b99
Rename rb_cfp_iseq to CFP_ISEQ and rb_cfp_pc to CFP_PC
k0kubun Mar 27, 2026
634707a
Rename CFP_HAS_JIT_RETURN to CFP_JIT_RETURN
k0kubun Mar 27, 2026
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
3 changes: 0 additions & 3 deletions .github/workflows/compilers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ jobs:
- { uses: './.github/actions/compilers', name: 'NDEBUG', with: { cppflags: '-DNDEBUG' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'RUBY_DEBUG', with: { cppflags: '-DRUBY_DEBUG' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'ARRAY_DEBUG', with: { cppflags: '-DARRAY_DEBUG' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'BIGNUM_DEBUG', with: { cppflags: '-DBIGNUM_DEBUG' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'CCAN_LIST_DEBUG', with: { cppflags: '-DCCAN_LIST_DEBUG' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'CPDEBUG=-1', with: { cppflags: '-DCPDEBUG=-1' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'ENC_DEBUG', with: { cppflags: '-DENC_DEBUG' }, timeout-minutes: 5 }
Expand Down Expand Up @@ -259,8 +258,6 @@ jobs:
with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github, persist-credentials: false }
- { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
- { uses: './.github/actions/compilers', name: 'USE_LAZY_LOAD', with: { cppflags: '-DUSE_LAZY_LOAD' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'USE_SYMBOL_GC=0', with: { cppflags: '-DUSE_SYMBOL_GC=0' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'USE_THREAD_CACHE=0', with: { cppflags: '-DUSE_THREAD_CACHE=0' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'USE_RUBY_DEBUG_LOG=1', with: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'USE_DEBUG_COUNTER', with: { cppflags: '-DUSE_DEBUG_COUNTER=1' }, timeout-minutes: 5 }
- { uses: './.github/actions/compilers', name: 'SHARABLE_MIDDLE_SUBSTRING', with: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' }, timeout-minutes: 5 }
Expand Down
5 changes: 0 additions & 5 deletions bignum.c
Original file line number Diff line number Diff line change
Expand Up @@ -2943,11 +2943,6 @@ bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, s
}
}


#ifndef BIGNUM_DEBUG
# define BIGNUM_DEBUG (0+RUBY_DEBUG)
#endif

static int
bigzero_p(VALUE x)
{
Expand Down
14 changes: 9 additions & 5 deletions cont.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ extern int madvise(caddr_t, size_t, int);
#include "vm_sync.h"
#include "id_table.h"
#include "ractor_core.h"
#include "zjit.h"

enum {
DEBUG = 0,
Expand Down Expand Up @@ -1455,8 +1456,11 @@ rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data)

const rb_control_frame_t *cfp = cont->ec->cfp;
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
if (cfp->pc && cfp->iseq && imemo_type((VALUE)cfp->iseq) == imemo_iseq) {
callback(cfp->iseq, data);
if (CFP_PC(cfp) && CFP_ISEQ(cfp)) {
const rb_iseq_t *iseq = CFP_ISEQ(cfp);
if (iseq && imemo_type((VALUE)iseq) == imemo_iseq) {
callback(iseq, data);
}
}
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
Expand All @@ -1476,7 +1480,7 @@ rb_yjit_cancel_jit_return(void *leave_exit, void *leave_exception)

const rb_control_frame_t *cfp = cont->ec->cfp;
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) {
if (cfp->jit_return && cfp->jit_return != leave_exception) {
if (CFP_JIT_RETURN(cfp) && cfp->jit_return != leave_exception) {
((rb_control_frame_t *)cfp)->jit_return = leave_exit;
}
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
Expand Down Expand Up @@ -1576,8 +1580,8 @@ show_vm_pcs(const rb_control_frame_t *cfp,
int i=0;
while (cfp != end_of_cfp) {
int pc = 0;
if (cfp->iseq) {
pc = cfp->pc - ISEQ_BODY(cfp->iseq)->iseq_encoded;
if (CFP_ISEQ(cfp)) {
pc = cfp->pc - ISEQ_BODY(CFP_ISEQ(cfp))->iseq_encoded;
}
fprintf(stderr, "%2d pc: %d\n", i++, pc);
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
Expand Down
8 changes: 8 additions & 0 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,7 @@ cont.$(OBJEXT): {$(VPATH)}vm_debug.h
cont.$(OBJEXT): {$(VPATH)}vm_opts.h
cont.$(OBJEXT): {$(VPATH)}vm_sync.h
cont.$(OBJEXT): {$(VPATH)}yjit.h
cont.$(OBJEXT): {$(VPATH)}zjit.h
debug.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
debug.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
debug.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down Expand Up @@ -5420,6 +5421,7 @@ error.$(OBJEXT): {$(VPATH)}vm_opts.h
error.$(OBJEXT): {$(VPATH)}vm_sync.h
error.$(OBJEXT): {$(VPATH)}warning.rbinc
error.$(OBJEXT): {$(VPATH)}yjit.h
error.$(OBJEXT): {$(VPATH)}zjit.h
eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
eval.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down Expand Up @@ -5689,6 +5691,7 @@ eval.$(OBJEXT): {$(VPATH)}vm_core.h
eval.$(OBJEXT): {$(VPATH)}vm_debug.h
eval.$(OBJEXT): {$(VPATH)}vm_opts.h
eval.$(OBJEXT): {$(VPATH)}vm_sync.h
eval.$(OBJEXT): {$(VPATH)}zjit.h
explicit_bzero.$(OBJEXT): {$(VPATH)}config.h
explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/attr/format.h
Expand Down Expand Up @@ -7827,6 +7830,7 @@ jit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
jit.$(OBJEXT): $(top_srcdir)/internal/bits.h
jit.$(OBJEXT): $(top_srcdir)/internal/box.h
jit.$(OBJEXT): $(top_srcdir)/internal/class.h
jit.$(OBJEXT): $(top_srcdir)/internal/compile.h
jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
jit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
jit.$(OBJEXT): $(top_srcdir)/internal/gc.h
Expand Down Expand Up @@ -8072,6 +8076,7 @@ jit.$(OBJEXT): {$(VPATH)}vm_core.h
jit.$(OBJEXT): {$(VPATH)}vm_debug.h
jit.$(OBJEXT): {$(VPATH)}vm_opts.h
jit.$(OBJEXT): {$(VPATH)}vm_sync.h
jit.$(OBJEXT): {$(VPATH)}zjit.h
load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
load.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down Expand Up @@ -18617,6 +18622,7 @@ thread.$(OBJEXT): {$(VPATH)}vm_core.h
thread.$(OBJEXT): {$(VPATH)}vm_debug.h
thread.$(OBJEXT): {$(VPATH)}vm_opts.h
thread.$(OBJEXT): {$(VPATH)}vm_sync.h
thread.$(OBJEXT): {$(VPATH)}zjit.h
time.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
time.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
time.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down Expand Up @@ -20212,6 +20218,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}vm_core.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_debug.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_opts.h
vm_backtrace.$(OBJEXT): {$(VPATH)}vm_sync.h
vm_backtrace.$(OBJEXT): {$(VPATH)}zjit.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down Expand Up @@ -20460,6 +20467,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}vm_core.h
vm_dump.$(OBJEXT): {$(VPATH)}vm_debug.h
vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c
vm_dump.$(OBJEXT): {$(VPATH)}vm_opts.h
vm_dump.$(OBJEXT): {$(VPATH)}zjit.h
vm_sync.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_sync.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_sync.$(OBJEXT): $(CCAN_DIR)/list/list.h
Expand Down
11 changes: 10 additions & 1 deletion error.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "ruby_assert.h"
#include "vm_core.h"
#include "yjit.h"
#include "zjit.h"

#include "builtin.h"

Expand Down Expand Up @@ -908,6 +909,10 @@ bug_report_file(const char *file, int line, rb_pid_t *pid)
int len = err_position_0(buf, sizeof(buf), file, line);

if (out) {
/* Disable buffering so crash report output is not lost if
* rb_vm_bugreport() triggers a secondary crash (e.g. SIGSEGV
* while walking JIT frames). */
setvbuf(out, NULL, _IONBF, 0);
if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len) return out;
fclose(out);
}
Expand Down Expand Up @@ -1081,6 +1086,10 @@ die(void)
_set_abort_behavior( 0, _CALL_REPORTFAULT);
#endif

/* Reset SIGABRT to default so that abort() does not trigger our custom
* handler (sigabrt), which would re-open the crash report file with "w"
* and truncate the report already written by rb_bug(). */
signal(SIGABRT, SIG_DFL);
abort();
}

Expand Down Expand Up @@ -2367,7 +2376,7 @@ name_err_init_attr(VALUE exc, VALUE recv, VALUE method)
rb_ivar_set(exc, id_name, method);
err_init_recv(exc, recv);
if (cfp && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_DUMMY) {
rb_ivar_set(exc, id_iseq, rb_iseqw_new(cfp->iseq));
rb_ivar_set(exc, id_iseq, rb_iseqw_new(CFP_ISEQ(cfp)));
}
return exc;
}
Expand Down
5 changes: 3 additions & 2 deletions eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "ruby/vm.h"
#include "vm_core.h"
#include "ractor_core.h"
#include "zjit.h"

NORETURN(static void rb_raise_jump(VALUE, VALUE));
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
Expand Down Expand Up @@ -2010,10 +2011,10 @@ errinfo_place(const rb_execution_context_t *ec)

while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
if (VM_FRAME_RUBYFRAME_P(cfp)) {
if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_RESCUE) {
if (ISEQ_BODY(CFP_ISEQ(cfp))->type == ISEQ_TYPE_RESCUE) {
return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
}
else if (ISEQ_BODY(cfp->iseq)->type == ISEQ_TYPE_ENSURE &&
else if (ISEQ_BODY(CFP_ISEQ(cfp))->type == ISEQ_TYPE_ENSURE &&
!THROW_DATA_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR]) &&
!FIXNUM_P(cfp->ep[VM_ENV_INDEX_LAST_LVAR])) {
return &cfp->ep[VM_ENV_INDEX_LAST_LVAR];
Expand Down
10 changes: 5 additions & 5 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,11 +1000,11 @@ gc_validate_pc(VALUE obj)

rb_execution_context_t *ec = GET_EC();
const rb_control_frame_t *cfp = ec->cfp;
if (cfp && VM_FRAME_RUBYFRAME_P(cfp) && cfp->pc) {
const VALUE *iseq_encoded = ISEQ_BODY(cfp->iseq)->iseq_encoded;
const VALUE *iseq_encoded_end = iseq_encoded + ISEQ_BODY(cfp->iseq)->iseq_size;
RUBY_ASSERT(cfp->pc >= iseq_encoded, "PC not set when allocating, breaking tracing");
RUBY_ASSERT(cfp->pc <= iseq_encoded_end, "PC not set when allocating, breaking tracing");
if (cfp && VM_FRAME_RUBYFRAME_P(cfp) && CFP_PC(cfp)) {
const VALUE *iseq_encoded = ISEQ_BODY(CFP_ISEQ(cfp))->iseq_encoded;
const VALUE *iseq_encoded_end = iseq_encoded + ISEQ_BODY(CFP_ISEQ(cfp))->iseq_size;
RUBY_ASSERT(CFP_PC(cfp) >= iseq_encoded, "PC not set when allocating, breaking tracing");
RUBY_ASSERT(CFP_PC(cfp) <= iseq_encoded_end, "PC not set when allocating, breaking tracing");
}
#endif
}
Expand Down
17 changes: 16 additions & 1 deletion jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
#include "insns.inc"
#include "insns_info.inc"
#include "iseq.h"
#include "internal/compile.h"
#include "internal/gc.h"
#include "vm_sync.h"
#include "internal/fixnum.h"
#include "internal/string.h"
#include "internal/class.h"
#include "internal/imemo.h"
#include "ruby/internal/core/rtypeddata.h"
#include "zjit.h"

#ifndef _WIN32
#include <sys/mman.h>
Expand Down Expand Up @@ -82,6 +84,19 @@ rb_iseq_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc)
return rb_vm_insn_addr2opcode((const void *)at_pc);
}

// Get the bare opcode given a program counter. Always returns the base
// instruction, stripping trace/zjit variants.
int
rb_iseq_bare_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc)
{
if (OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE) {
RUBY_ASSERT_ALWAYS(FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED));
}

const VALUE at_pc = *pc;
return rb_vm_insn_addr2insn((const void *)at_pc);
}

unsigned long
rb_RSTRING_LEN(VALUE str)
{
Expand Down Expand Up @@ -388,7 +403,7 @@ rb_get_ec_cfp(const rb_execution_context_t *ec)
const rb_iseq_t *
rb_get_cfp_iseq(struct rb_control_frame_struct *cfp)
{
return cfp->iseq;
return CFP_ISEQ(cfp);
}

VALUE *
Expand Down
2 changes: 1 addition & 1 deletion lib/prism/translation/ripper/shim.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

# This writes the prism ripper translation into the Ripper constant so that
# users can transparently use Ripper without any changes.
Ripper = Prism::Translation::Ripper
Ripper = Prism::Translation::Ripper # :nodoc:
7 changes: 0 additions & 7 deletions symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@
#include "builtin.h"
#include "ruby/internal/attr/nonstring.h"

#if defined(USE_SYMBOL_GC) && !(USE_SYMBOL_GC+0)
# undef USE_SYMBOL_GC
# define USE_SYMBOL_GC 0
#else
# undef USE_SYMBOL_GC
# define USE_SYMBOL_GC 1
#endif
#if defined(SYMBOL_DEBUG) && (SYMBOL_DEBUG+0)
# undef SYMBOL_DEBUG
# define SYMBOL_DEBUG 1
Expand Down
11 changes: 6 additions & 5 deletions thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include "ractor_core.h"
#include "vm_debug.h"
#include "vm_sync.h"
#include "zjit.h"

#include "ccan/list/list.h"

Expand Down Expand Up @@ -5905,7 +5906,7 @@ static void
update_line_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
{
const rb_control_frame_t *cfp = GET_EC()->cfp;
VALUE coverage = rb_iseq_coverage(cfp->iseq);
VALUE coverage = rb_iseq_coverage(CFP_ISEQ(cfp));
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
VALUE lines = RARRAY_AREF(coverage, COVERAGE_INDEX_LINES);
if (lines) {
Expand All @@ -5915,7 +5916,7 @@ update_line_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
VALUE num;
void rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset);
if (GET_VM()->coverage_mode & COVERAGE_TARGET_ONESHOT_LINES) {
rb_iseq_clear_event_flags(cfp->iseq, cfp->pc - ISEQ_BODY(cfp->iseq)->iseq_encoded - 1, RUBY_EVENT_COVERAGE_LINE);
rb_iseq_clear_event_flags(CFP_ISEQ(cfp), CFP_PC(cfp) - ISEQ_BODY(CFP_ISEQ(cfp))->iseq_encoded - 1, RUBY_EVENT_COVERAGE_LINE);
rb_ary_push(lines, LONG2FIX(line + 1));
return;
}
Expand All @@ -5936,12 +5937,12 @@ static void
update_branch_coverage(VALUE data, const rb_trace_arg_t *trace_arg)
{
const rb_control_frame_t *cfp = GET_EC()->cfp;
VALUE coverage = rb_iseq_coverage(cfp->iseq);
VALUE coverage = rb_iseq_coverage(CFP_ISEQ(cfp));
if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) {
VALUE branches = RARRAY_AREF(coverage, COVERAGE_INDEX_BRANCHES);
if (branches) {
long pc = cfp->pc - ISEQ_BODY(cfp->iseq)->iseq_encoded - 1;
long idx = FIX2INT(RARRAY_AREF(ISEQ_PC2BRANCHINDEX(cfp->iseq), pc)), count;
long pc = CFP_PC(cfp) - ISEQ_BODY(CFP_ISEQ(cfp))->iseq_encoded - 1;
long idx = FIX2INT(RARRAY_AREF(ISEQ_PC2BRANCHINDEX(CFP_ISEQ(cfp)), pc)), count;
VALUE counters = RARRAY_AREF(branches, 1);
VALUE num = RARRAY_AREF(counters, idx);
count = FIX2LONG(num) + 1;
Expand Down
Loading