diff options
-rw-r--r-- | bootstraptest/test_yjit.rb | 14 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 26 | ||||
-rw-r--r-- | yjit/src/core.rs | 6 |
3 files changed, 42 insertions, 4 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index ae67c91a76..31bb626690 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4830,6 +4830,20 @@ assert_equal "abc", %q{ str } +# test --yjit-verify-ctx for arrays with a singleton class +assert_equal "ok", %q{ + class Array + def foo + self.singleton_class.define_method(:first) { :ok } + first + end + end + + def test = [].foo + + test +} + assert_equal '["raised", "Module", "Object"]', %q{ def foo(obj) obj.superclass.name diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index a5fc3a10a1..000f9fb516 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -567,14 +567,36 @@ fn verify_ctx(jit: &JITState, ctx: &Context) { unsafe { CStr::from_ptr(rb_obj_info(val)).to_str().unwrap() } } + // Some types such as CString only assert the class field of the object + // when there has never been a singleton class created for objects of that class. + // Once there is a singleton class created they become their weaker + // `T*` variant, and we more objects should pass the verification. + fn relax_type_with_singleton_class_assumption(ty: Type) -> Type { + if let Type::CString | Type::CArray | Type::CHash = ty { + if has_singleton_class_of(ty.known_class().unwrap()) { + match ty { + Type::CString => return Type::TString, + Type::CArray => return Type::TArray, + Type::CHash => return Type::THash, + _ => (), + } + } + } + + ty + } + // Only able to check types when at current insn assert!(jit.at_current_insn()); let self_val = jit.peek_at_self(); let self_val_type = Type::from(self_val); + let learned_self_type = ctx.get_opnd_type(SelfOpnd); + let learned_self_type = relax_type_with_singleton_class_assumption(learned_self_type); + // Verify self operand type - if self_val_type.diff(ctx.get_opnd_type(SelfOpnd)) == TypeDiff::Incompatible { + if self_val_type.diff(learned_self_type) == TypeDiff::Incompatible { panic!( "verify_ctx: ctx self type ({:?}) incompatible with actual value of self {}", ctx.get_opnd_type(SelfOpnd), @@ -587,6 +609,7 @@ fn verify_ctx(jit: &JITState, ctx: &Context) { for i in 0..top_idx { let learned_mapping = ctx.get_opnd_mapping(StackOpnd(i)); let learned_type = ctx.get_opnd_type(StackOpnd(i)); + let learned_type = relax_type_with_singleton_class_assumption(learned_type); let stack_val = jit.peek_at_stack(ctx, i as isize); let val_type = Type::from(stack_val); @@ -632,6 +655,7 @@ fn verify_ctx(jit: &JITState, ctx: &Context) { let top_idx: usize = cmp::min(local_table_size as usize, MAX_TEMP_TYPES); for i in 0..top_idx { let learned_type = ctx.get_local_type(i); + let learned_type = relax_type_with_singleton_class_assumption(learned_type); let local_val = jit.peek_at_local(i as i32); let local_type = Type::from(local_val); diff --git a/yjit/src/core.rs b/yjit/src/core.rs index ceba1069e6..0302ecd536 100644 --- a/yjit/src/core.rs +++ b/yjit/src/core.rs @@ -53,11 +53,11 @@ pub enum Type { ImmSymbol, 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 object that at one point had its class field equal rb_cString (creating a singleton class changes it) TArray, // An object with the T_ARRAY flag set, possibly an rb_cArray - CArray, // An un-subclassed array of type rb_cArray (can have instance vars in some cases) + CArray, // An object that at one point had its class field equal rb_cArray (creating a singleton class changes it) THash, // An object with the T_HASH flag set, possibly an rb_cHash - CHash, // An un-subclassed hash of type rb_cHash (can have instance vars in some cases) + CHash, // An object that at one point had its class field equal rb_cHash (creating a singleton class changes it) BlockParamProxy, // A special sentinel value indicating the block parameter should be read from // the current surrounding cfp |