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());
|
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);
|
asm.mov(stack_ret, new_ary);
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
@ -1185,7 +1185,7 @@ fn gen_duparray(
|
|||||||
vec![ary.into()],
|
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);
|
asm.mov(stack_ret, new_ary);
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
@ -1231,7 +1231,7 @@ fn gen_splatarray(
|
|||||||
// Call rb_vm_splat_array(flag, ary)
|
// Call rb_vm_splat_array(flag, ary)
|
||||||
let ary = asm.ccall(rb_vm_splat_array as *const u8, vec![flag.into(), ary_opnd]);
|
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);
|
asm.mov(stack_ret, ary);
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
@ -1255,7 +1255,7 @@ fn gen_concatarray(
|
|||||||
// Call rb_vm_concat_array(ary1, ary2st)
|
// Call rb_vm_concat_array(ary1, ary2st)
|
||||||
let ary = asm.ccall(rb_vm_concat_array as *const u8, vec![ary1_opnd, ary2st_opnd]);
|
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);
|
asm.mov(stack_ret, ary);
|
||||||
|
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
@ -3886,6 +3886,8 @@ fn jit_guard_known_klass(
|
|||||||
|
|
||||||
if known_klass == unsafe { rb_cString } {
|
if known_klass == unsafe { rb_cString } {
|
||||||
ctx.upgrade_opnd_type(insn_opnd, Type::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,
|
False,
|
||||||
Fixnum,
|
Fixnum,
|
||||||
Flonum,
|
Flonum,
|
||||||
Array,
|
|
||||||
Hash,
|
Hash,
|
||||||
ImmSymbol,
|
ImmSymbol,
|
||||||
|
|
||||||
@ -44,6 +43,8 @@ pub enum Type {
|
|||||||
|
|
||||||
TString, // An object with the T_STRING flag set, possibly an rb_cString
|
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)
|
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
|
BlockParamProxy, // A special sentinel value indicating the block parameter should be read from
|
||||||
// the current surrounding cfp
|
// the current surrounding cfp
|
||||||
@ -82,6 +83,10 @@ impl Type {
|
|||||||
if val.class_of() == unsafe { rb_cString } {
|
if val.class_of() == unsafe { rb_cString } {
|
||||||
return Type::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 likewise can't reference rb_block_param_proxy, but it's again an optimisation;
|
||||||
// we can just treat it as a normal Object.
|
// we can just treat it as a normal Object.
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
@ -89,7 +94,7 @@ impl Type {
|
|||||||
return Type::BlockParamProxy;
|
return Type::BlockParamProxy;
|
||||||
}
|
}
|
||||||
match val.builtin_type() {
|
match val.builtin_type() {
|
||||||
RUBY_T_ARRAY => Type::Array,
|
RUBY_T_ARRAY => Type::TArray,
|
||||||
RUBY_T_HASH => Type::Hash,
|
RUBY_T_HASH => Type::Hash,
|
||||||
RUBY_T_STRING => Type::TString,
|
RUBY_T_STRING => Type::TString,
|
||||||
_ => Type::UnknownHeap,
|
_ => Type::UnknownHeap,
|
||||||
@ -130,7 +135,8 @@ impl Type {
|
|||||||
pub fn is_heap(&self) -> bool {
|
pub fn is_heap(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Type::UnknownHeap => true,
|
Type::UnknownHeap => true,
|
||||||
Type::Array => true,
|
Type::TArray => true,
|
||||||
|
Type::CArray => true,
|
||||||
Type::Hash => true,
|
Type::Hash => true,
|
||||||
Type::HeapSymbol => true,
|
Type::HeapSymbol => true,
|
||||||
Type::TString => true,
|
Type::TString => true,
|
||||||
@ -147,7 +153,7 @@ impl Type {
|
|||||||
Type::False => Some(RUBY_T_FALSE),
|
Type::False => Some(RUBY_T_FALSE),
|
||||||
Type::Fixnum => Some(RUBY_T_FIXNUM),
|
Type::Fixnum => Some(RUBY_T_FIXNUM),
|
||||||
Type::Flonum => Some(RUBY_T_FLOAT),
|
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::Hash => Some(RUBY_T_HASH),
|
||||||
Type::ImmSymbol | Type::HeapSymbol => Some(RUBY_T_SYMBOL),
|
Type::ImmSymbol | Type::HeapSymbol => Some(RUBY_T_SYMBOL),
|
||||||
Type::TString | Type::CString => Some(RUBY_T_STRING),
|
Type::TString | Type::CString => Some(RUBY_T_STRING),
|
||||||
@ -167,6 +173,7 @@ impl Type {
|
|||||||
Type::Flonum => Some(rb_cFloat),
|
Type::Flonum => Some(rb_cFloat),
|
||||||
Type::ImmSymbol | Type::HeapSymbol => Some(rb_cSymbol),
|
Type::ImmSymbol | Type::HeapSymbol => Some(rb_cSymbol),
|
||||||
Type::CString => Some(rb_cString),
|
Type::CString => Some(rb_cString),
|
||||||
|
Type::CArray => Some(rb_cArray),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,6 +231,11 @@ impl Type {
|
|||||||
return 1;
|
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
|
// Specific heap type into unknown heap type is imperfect but valid
|
||||||
if self.is_heap() && dst == Type::UnknownHeap {
|
if self.is_heap() && dst == Type::UnknownHeap {
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user