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>
This commit is contained in:
parent
aeddc19340
commit
5bf7218b01
Notes:
git
2023-01-10 18:54:28 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user