diff options
author | Alan Wu <[email protected]> | 2024-10-21 18:08:51 -0400 |
---|---|---|
committer | Alan Wu <[email protected]> | 2024-10-22 11:30:35 -0400 |
commit | b41c65b57735ce0d556b6fdad0ce490e939b1c7a (patch) | |
tree | 250a9a3904284d412a3ad37bc57ac49ca0b124da | |
parent | 3a327e1c18df5439920d2a54ba68d82dd069326b (diff) |
YJIT: Implement specialization for no-op `{Kernel,Numeric}#dup`
Type information in the context for no additional work!
This is the `if (special_object_p(obj)) return obj;` path in
rb_obj_dup() and for Numeric#dup, it's always the identity function.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/11926
-rw-r--r-- | yjit/bindgen/src/main.rs | 1 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 39 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 1 |
3 files changed, 41 insertions, 0 deletions
diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 649d540c94..5f0f599b9a 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -167,6 +167,7 @@ fn main() { .allowlist_var("rb_cIO") .allowlist_var("rb_cSymbol") .allowlist_var("rb_cFloat") + .allowlist_var("rb_cNumeric") .allowlist_var("rb_cString") .allowlist_var("rb_cThread") .allowlist_var("rb_cArray") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index ed8fc65491..6e2f96724a 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6347,6 +6347,42 @@ fn jit_thread_s_current( true } +fn jit_numeric_dup( + _jit: &mut JITState, + _asm: &mut Assembler, + _ci: *const rb_callinfo, + _cme: *const rb_callable_method_entry_t, + _block: Option<BlockHandler>, + _argc: i32, + _known_recv_class: Option<VALUE>, +) -> bool { + // Numeric#dup has arity=0 and is the identity function. + // Our caller already did argument count check, so this is + // no-op to return the receiver that is already on the stack. + true +} + +/// Specialization for rb_obj_dup() (Kernel#dup) +fn jit_rb_obj_dup( + _jit: &mut JITState, + asm: &mut Assembler, + _ci: *const rb_callinfo, + _cme: *const rb_callable_method_entry_t, + _block: Option<BlockHandler>, + _argc: i32, + _known_recv_class: Option<VALUE>, +) -> bool { + // Kernel#dup has arity=0, and caller already did argument count check. + let self_type = asm.ctx.get_opnd_type(StackOpnd(0)); + + if self_type.is_imm() { + // Method is no-op when receiver is an immediate value. + true + } else { + false + } +} + /// Check if we know how to codegen for a particular cfunc method /// See also: [reg_method_codegen]. fn lookup_cfunc_codegen(def: *const rb_method_definition_t) -> Option<MethodGenFn> { @@ -10424,6 +10460,8 @@ pub fn yjit_reg_method_codegen_fns() { reg_method_codegen(rb_cFloat, "*", jit_rb_float_mul); reg_method_codegen(rb_cFloat, "/", jit_rb_float_div); + reg_method_codegen(rb_cNumeric, "dup", jit_numeric_dup); + reg_method_codegen(rb_cString, "empty?", jit_rb_str_empty_p); reg_method_codegen(rb_cString, "to_s", jit_rb_str_to_s); reg_method_codegen(rb_cString, "to_str", jit_rb_str_to_s); @@ -10449,6 +10487,7 @@ pub fn yjit_reg_method_codegen_fns() { reg_method_codegen(rb_mKernel, "respond_to?", jit_obj_respond_to); reg_method_codegen(rb_mKernel, "block_given?", jit_rb_f_block_given_p); + reg_method_codegen(rb_mKernel, "dup", jit_rb_obj_dup); reg_method_codegen(rb_cClass, "superclass", jit_rb_class_superclass); diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 8b53098cc9..4eb44634a1 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -997,6 +997,7 @@ extern "C" { pub static mut rb_cInteger: VALUE; pub static mut rb_cModule: VALUE; pub static mut rb_cNilClass: VALUE; + pub static mut rb_cNumeric: VALUE; pub static mut rb_cString: VALUE; pub static mut rb_cSymbol: VALUE; pub static mut rb_cThread: VALUE; |