summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2023-01-10 10:54:07 -0800
committerGitHub <noreply@github.com>2023-01-10 13:54:07 -0500
commit5bf7218b01375b635188795dc4494562c2a98ea6 (patch)
tree7dfd178ce24a648e746263885c2cb679de2835b8
parentaeddc19340c7116d48fac3080553fbb823857d16 (diff)
Differentiate T_ARRAY and array subclasses (#7091)
* Differentiate T_ARRAY and array subclasses This commit teaches the YJIT context the difference between Arrays (objects with type T_ARRAY and class rb_cArray) vs Array subclasses (objects with type T_ARRAY but _not_ class rb_cArray). It uses this information to reduce the number of guards emitted when using `jit_guard_known_klass` with rb_cArray, notably opt_aref * Update yjit/src/core.rs Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Notes
Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
-rw-r--r--yjit/src/codegen.rs10
-rw-r--r--yjit/src/core.rs20
2 files changed, 22 insertions, 8 deletions
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index a7c2b37eeb..3dbc589466 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -1161,7 +1161,7 @@ fn gen_newarray(
);
ctx.stack_pop(n.as_usize());
- let stack_ret = ctx.stack_push(Type::Array);
+ let stack_ret = ctx.stack_push(Type::CArray);
asm.mov(stack_ret, new_ary);
KeepCompiling
@@ -1185,7 +1185,7 @@ fn gen_duparray(
vec![ary.into()],
);
- let stack_ret = ctx.stack_push(Type::Array);
+ let stack_ret = ctx.stack_push(Type::CArray);
asm.mov(stack_ret, new_ary);
KeepCompiling
@@ -1231,7 +1231,7 @@ fn gen_splatarray(
// Call rb_vm_splat_array(flag, ary)
let ary = asm.ccall(rb_vm_splat_array as *const u8, vec![flag.into(), ary_opnd]);
- let stack_ret = ctx.stack_push(Type::Array);
+ let stack_ret = ctx.stack_push(Type::TArray);
asm.mov(stack_ret, ary);
KeepCompiling
@@ -1255,7 +1255,7 @@ fn gen_concatarray(
// Call rb_vm_concat_array(ary1, ary2st)
let ary = asm.ccall(rb_vm_concat_array as *const u8, vec![ary1_opnd, ary2st_opnd]);
- let stack_ret = ctx.stack_push(Type::Array);
+ let stack_ret = ctx.stack_push(Type::TArray);
asm.mov(stack_ret, ary);
KeepCompiling
@@ -3886,6 +3886,8 @@ fn jit_guard_known_klass(
if known_klass == unsafe { rb_cString } {
ctx.upgrade_opnd_type(insn_opnd, Type::CString);
+ } else if known_klass == unsafe { rb_cArray } {
+ ctx.upgrade_opnd_type(insn_opnd, Type::CArray);
}
}
}
diff --git a/yjit/src/core.rs b/yjit/src/core.rs
index 3b471e782e..71c9ae5a9e 100644
--- a/yjit/src/core.rs
+++ b/yjit/src/core.rs
@@ -35,7 +35,6 @@ pub enum Type {
False,
Fixnum,
Flonum,
- Array,
Hash,
ImmSymbol,
@@ -44,6 +43,8 @@ pub enum Type {
TString, // An object with the T_STRING flag set, possibly an rb_cString
CString, // An un-subclassed string of type rb_cString (can have instance vars in some cases)
+ TArray, // An object with the T_ARRAY flag set, possibly an rb_cArray
+ CArray, // An un-subclassed string of type rb_cArray (can have instance vars in some cases)
BlockParamProxy, // A special sentinel value indicating the block parameter should be read from
// the current surrounding cfp
@@ -82,6 +83,10 @@ impl Type {
if val.class_of() == unsafe { rb_cString } {
return Type::CString;
}
+ #[cfg(not(test))]
+ if val.class_of() == unsafe { rb_cArray } {
+ return Type::CArray;
+ }
// We likewise can't reference rb_block_param_proxy, but it's again an optimisation;
// we can just treat it as a normal Object.
#[cfg(not(test))]
@@ -89,7 +94,7 @@ impl Type {
return Type::BlockParamProxy;
}
match val.builtin_type() {
- RUBY_T_ARRAY => Type::Array,
+ RUBY_T_ARRAY => Type::TArray,
RUBY_T_HASH => Type::Hash,
RUBY_T_STRING => Type::TString,
_ => Type::UnknownHeap,
@@ -130,7 +135,8 @@ impl Type {
pub fn is_heap(&self) -> bool {
match self {
Type::UnknownHeap => true,
- Type::Array => true,
+ Type::TArray => true,
+ Type::CArray => true,
Type::Hash => true,
Type::HeapSymbol => true,
Type::TString => true,
@@ -147,7 +153,7 @@ impl Type {
Type::False => Some(RUBY_T_FALSE),
Type::Fixnum => Some(RUBY_T_FIXNUM),
Type::Flonum => Some(RUBY_T_FLOAT),
- Type::Array => Some(RUBY_T_ARRAY),
+ Type::TArray | Type::CArray => Some(RUBY_T_ARRAY),
Type::Hash => Some(RUBY_T_HASH),
Type::ImmSymbol | Type::HeapSymbol => Some(RUBY_T_SYMBOL),
Type::TString | Type::CString => Some(RUBY_T_STRING),
@@ -167,6 +173,7 @@ impl Type {
Type::Flonum => Some(rb_cFloat),
Type::ImmSymbol | Type::HeapSymbol => Some(rb_cSymbol),
Type::CString => Some(rb_cString),
+ Type::CArray => Some(rb_cArray),
_ => None,
}
}
@@ -224,6 +231,11 @@ impl Type {
return 1;
}
+ // A CArray is also a TArray.
+ if self == Type::CArray && dst == Type::TArray {
+ return 1;
+ }
+
// Specific heap type into unknown heap type is imperfect but valid
if self.is_heap() && dst == Type::UnknownHeap {
return 1;