summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <[email protected]>2024-10-21 18:08:51 -0400
committerAlan Wu <[email protected]>2024-10-22 11:30:35 -0400
commitb41c65b57735ce0d556b6fdad0ce490e939b1c7a (patch)
tree250a9a3904284d412a3ad37bc57ac49ca0b124da
parent3a327e1c18df5439920d2a54ba68d82dd069326b (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.rs1
-rw-r--r--yjit/src/codegen.rs39
-rw-r--r--yjit/src/cruby_bindings.inc.rs1
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;