Disable ZJIT profiling at call-threshold (https://github.com/Shopify/zjit/pull/99)
* Disable ZJIT profiling at call-threshold * Stop referencing ZJIT instructions in codegen
This commit is contained in:
parent
2915806820
commit
8b72e07359
Notes:
git
2025-04-18 13:47:42 +00:00
@ -1,7 +1,6 @@
|
||||
MAYBE_UNUSED(static int vm_insn_to_zjit_insn(int insn));
|
||||
|
||||
MAYBE_UNUSED(static int vm_bare_insn_to_zjit_insn(int insn));
|
||||
static int
|
||||
vm_insn_to_zjit_insn(int insn)
|
||||
vm_bare_insn_to_zjit_insn(int insn)
|
||||
{
|
||||
switch (insn) {
|
||||
% RubyVM::ZJITInstructions.to_a.each do |insn|
|
||||
@ -12,3 +11,17 @@ vm_insn_to_zjit_insn(int insn)
|
||||
return insn;
|
||||
}
|
||||
}
|
||||
|
||||
MAYBE_UNUSED(static int vm_zjit_insn_to_bare_insn(int insn));
|
||||
static int
|
||||
vm_zjit_insn_to_bare_insn(int insn)
|
||||
{
|
||||
switch (insn) {
|
||||
% RubyVM::ZJITInstructions.to_a.each do |insn|
|
||||
case <%= insn.bin %>:
|
||||
return BIN(<%= insn.jump_destination %>);
|
||||
% end
|
||||
default:
|
||||
return insn;
|
||||
}
|
||||
}
|
||||
|
2
vm.c
2
vm.c
@ -443,7 +443,7 @@ jit_compile(rb_execution_context_t *ec)
|
||||
// At profile-threshold, rewrite some of the YARV instructions
|
||||
// to zjit_* instructions to profile these instructions.
|
||||
if (body->jit_entry_calls == rb_zjit_profile_threshold) {
|
||||
rb_zjit_profile_iseq(iseq);
|
||||
rb_zjit_profile_enable(iseq);
|
||||
}
|
||||
|
||||
// At call-threshold, compile the ISEQ with ZJIT.
|
||||
|
27
zjit.c
27
zjit.c
@ -168,12 +168,17 @@ rb_RSTRING_PTR(VALUE str)
|
||||
return RSTRING_PTR(str);
|
||||
}
|
||||
|
||||
void rb_zjit_profile_disable(const rb_iseq_t *iseq);
|
||||
|
||||
void
|
||||
rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception)
|
||||
{
|
||||
RB_VM_LOCK_ENTER();
|
||||
rb_vm_barrier();
|
||||
|
||||
// Convert ZJIT instructions back to bare instructions
|
||||
rb_zjit_profile_disable(iseq);
|
||||
|
||||
// Compile a block version starting at the current instruction
|
||||
uint8_t *rb_zjit_iseq_gen_entry_point(const rb_iseq_t *iseq, rb_execution_context_t *ec); // defined in Rust
|
||||
uintptr_t code_ptr = (uintptr_t)rb_zjit_iseq_gen_entry_point(iseq, ec);
|
||||
@ -652,7 +657,7 @@ rb_RCLASS_ORIGIN(VALUE c)
|
||||
|
||||
// Convert a given ISEQ's instructions to zjit_* instructions
|
||||
void
|
||||
rb_zjit_profile_iseq(const rb_iseq_t *iseq)
|
||||
rb_zjit_profile_enable(const rb_iseq_t *iseq)
|
||||
{
|
||||
// This table encodes an opcode into the instruction's address
|
||||
const void *const *insn_table = rb_vm_get_insns_address_table();
|
||||
@ -660,7 +665,7 @@ rb_zjit_profile_iseq(const rb_iseq_t *iseq)
|
||||
unsigned int insn_idx = 0;
|
||||
while (insn_idx < iseq->body->iseq_size) {
|
||||
int insn = rb_vm_insn_decode(iseq->body->iseq_encoded[insn_idx]);
|
||||
int zjit_insn = vm_insn_to_zjit_insn(insn);
|
||||
int zjit_insn = vm_bare_insn_to_zjit_insn(insn);
|
||||
if (insn != zjit_insn) {
|
||||
iseq->body->iseq_encoded[insn_idx] = (VALUE)insn_table[zjit_insn];
|
||||
}
|
||||
@ -668,6 +673,24 @@ rb_zjit_profile_iseq(const rb_iseq_t *iseq)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a given ISEQ's ZJIT instructions to bare instructions
|
||||
void
|
||||
rb_zjit_profile_disable(const rb_iseq_t *iseq)
|
||||
{
|
||||
// This table encodes an opcode into the instruction's address
|
||||
const void *const *insn_table = rb_vm_get_insns_address_table();
|
||||
|
||||
unsigned int insn_idx = 0;
|
||||
while (insn_idx < iseq->body->iseq_size) {
|
||||
int insn = rb_vm_insn_decode(iseq->body->iseq_encoded[insn_idx]);
|
||||
int bare_insn = vm_zjit_insn_to_bare_insn(insn);
|
||||
if (insn != bare_insn) {
|
||||
iseq->body->iseq_encoded[insn_idx] = (VALUE)insn_table[bare_insn];
|
||||
}
|
||||
insn_idx += insn_len(insn);
|
||||
}
|
||||
}
|
||||
|
||||
// Get profiling information for ISEQ
|
||||
void *
|
||||
rb_iseq_get_zjit_payload(const rb_iseq_t *iseq)
|
||||
|
4
zjit.h
4
zjit.h
@ -10,13 +10,13 @@ extern uint64_t rb_zjit_call_threshold;
|
||||
extern uint64_t rb_zjit_profile_threshold;
|
||||
void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception);
|
||||
void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec);
|
||||
void rb_zjit_profile_iseq(const rb_iseq_t *iseq);
|
||||
void rb_zjit_profile_enable(const rb_iseq_t *iseq);
|
||||
void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
|
||||
void rb_zjit_invalidate_ep_is_bp(const rb_iseq_t *iseq);
|
||||
#else
|
||||
static inline void rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit_exception) {}
|
||||
static inline void rb_zjit_profile_insn(enum ruby_vminsn_type insn, rb_execution_context_t *ec) {}
|
||||
static inline void rb_zjit_profile_iseq(const rb_iseq_t *iseq) {}
|
||||
static inline void rb_zjit_profile_enable(const rb_iseq_t *iseq) {}
|
||||
static inline void rb_zjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
|
||||
static inline void rb_zjit_invalidate_ep_is_bp(const rb_iseq_t *iseq) {}
|
||||
#endif // #if USE_YJIT
|
||||
|
@ -100,6 +100,7 @@ fn main() {
|
||||
.allowlist_function("ruby_executable_node")
|
||||
.allowlist_function("rb_funcallv")
|
||||
.allowlist_function("rb_protect")
|
||||
.allowlist_function("rb_zjit_profile_disable")
|
||||
|
||||
// For crashing
|
||||
.allowlist_function("rb_bug")
|
||||
|
1
zjit/src/cruby_bindings.inc.rs
generated
1
zjit/src/cruby_bindings.inc.rs
generated
@ -945,6 +945,7 @@ unsafe extern "C" {
|
||||
pub fn rb_zjit_reserve_addr_space(mem_size: u32) -> *mut u8;
|
||||
pub fn rb_RSTRING_LEN(str_: VALUE) -> ::std::os::raw::c_ulong;
|
||||
pub fn rb_RSTRING_PTR(str_: VALUE) -> *mut ::std::os::raw::c_char;
|
||||
pub fn rb_zjit_profile_disable(iseq: *const rb_iseq_t);
|
||||
pub fn rb_iseq_encoded_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint;
|
||||
pub fn rb_iseq_opcode_at_pc(iseq: *const rb_iseq_t, pc: *const VALUE) -> ::std::os::raw::c_int;
|
||||
pub fn rb_iseq_pc_at_idx(iseq: *const rb_iseq_t, insn_idx: u32) -> *mut VALUE;
|
||||
|
@ -1598,38 +1598,38 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
||||
}
|
||||
}
|
||||
|
||||
YARVINSN_opt_plus | YARVINSN_zjit_opt_plus => {
|
||||
YARVINSN_opt_plus => {
|
||||
push_fixnum_insn!(FixnumAdd, "+", BOP_PLUS, state);
|
||||
}
|
||||
YARVINSN_opt_minus | YARVINSN_zjit_opt_minus => {
|
||||
YARVINSN_opt_minus => {
|
||||
push_fixnum_insn!(FixnumSub, "-", BOP_MINUS, state);
|
||||
}
|
||||
YARVINSN_opt_mult | YARVINSN_zjit_opt_mult => {
|
||||
YARVINSN_opt_mult => {
|
||||
push_fixnum_insn!(FixnumMult, "*", BOP_MULT, state);
|
||||
}
|
||||
YARVINSN_opt_div | YARVINSN_zjit_opt_div => {
|
||||
YARVINSN_opt_div => {
|
||||
push_fixnum_insn!(FixnumDiv, "/", BOP_DIV, state);
|
||||
}
|
||||
YARVINSN_opt_mod | YARVINSN_zjit_opt_mod => {
|
||||
YARVINSN_opt_mod => {
|
||||
push_fixnum_insn!(FixnumMod, "%", BOP_MOD, state);
|
||||
}
|
||||
|
||||
YARVINSN_opt_eq | YARVINSN_zjit_opt_eq => {
|
||||
YARVINSN_opt_eq => {
|
||||
push_fixnum_insn!(FixnumEq, "==", BOP_EQ);
|
||||
}
|
||||
YARVINSN_opt_neq | YARVINSN_zjit_opt_neq => {
|
||||
YARVINSN_opt_neq => {
|
||||
push_fixnum_insn!(FixnumNeq, "!=", BOP_NEQ);
|
||||
}
|
||||
YARVINSN_opt_lt | YARVINSN_zjit_opt_lt => {
|
||||
YARVINSN_opt_lt => {
|
||||
push_fixnum_insn!(FixnumLt, "<", BOP_LT);
|
||||
}
|
||||
YARVINSN_opt_le | YARVINSN_zjit_opt_le => {
|
||||
YARVINSN_opt_le => {
|
||||
push_fixnum_insn!(FixnumLe, "<=", BOP_LE);
|
||||
}
|
||||
YARVINSN_opt_gt | YARVINSN_zjit_opt_gt => {
|
||||
YARVINSN_opt_gt => {
|
||||
push_fixnum_insn!(FixnumGt, ">", BOP_GT);
|
||||
}
|
||||
YARVINSN_opt_ge | YARVINSN_zjit_opt_ge => {
|
||||
YARVINSN_opt_ge => {
|
||||
push_fixnum_insn!(FixnumGe, ">==", BOP_GE);
|
||||
}
|
||||
YARVINSN_opt_ltlt => {
|
||||
@ -1654,7 +1654,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
||||
break; // Don't enqueue the next block as a successor
|
||||
}
|
||||
|
||||
YARVINSN_opt_send_without_block | YARVINSN_zjit_opt_send_without_block => {
|
||||
YARVINSN_opt_send_without_block => {
|
||||
let cd: *const rb_call_data = get_arg(pc, 0).as_ptr();
|
||||
let call_info = unsafe { rb_get_call_data_ci(cd) };
|
||||
let argc = unsafe { vm_ci_argc((*cd).ci) };
|
||||
@ -1991,6 +1991,7 @@ mod tests {
|
||||
#[track_caller]
|
||||
fn assert_method_hir(method: &str, hir: Expect) {
|
||||
let iseq = crate::cruby::with_rubyvm(|| get_method_iseq(method));
|
||||
unsafe { crate::cruby::rb_zjit_profile_disable(iseq) };
|
||||
let function = iseq_to_hir(iseq).unwrap();
|
||||
assert_function_hir(function, hir);
|
||||
}
|
||||
@ -2531,6 +2532,7 @@ mod opt_tests {
|
||||
#[track_caller]
|
||||
fn assert_optimized_method_hir(method: &str, hir: Expect) {
|
||||
let iseq = crate::cruby::with_rubyvm(|| get_method_iseq(method));
|
||||
unsafe { crate::cruby::rb_zjit_profile_disable(iseq) };
|
||||
let mut function = iseq_to_hir(iseq).unwrap();
|
||||
function.optimize();
|
||||
assert_function_hir(function, hir);
|
||||
|
Loading…
x
Reference in New Issue
Block a user