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;