ZJIT: Parse putspecialobject(VMCore) into Const (#13683)

This way we get more information in HIR for the optimizer.

Fix https://github.com/Shopify/ruby/issues/587
This commit is contained in:
Max Bernstein 2025-06-23 18:55:37 -05:00 committed by GitHub
parent 3a9bf4a2ae
commit 74e6bddf15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 14 additions and 7 deletions

View file

@ -2328,7 +2328,12 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
YARVINSN_putobject => { state.stack_push(fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) })); },
YARVINSN_putspecialobject => {
let value_type = SpecialObjectType::from(get_arg(pc, 0).as_u32());
state.stack_push(fun.push_insn(block, Insn::PutSpecialObject { value_type }));
let insn = if value_type == SpecialObjectType::VMCore {
Insn::Const { val: Const::Value(unsafe { rb_mRubyVMFrozenCore }) }
} else {
Insn::PutSpecialObject { value_type }
};
state.stack_push(fun.push_insn(block, insn));
}
YARVINSN_putstring => {
let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) });
@ -3922,11 +3927,11 @@ mod tests {
assert_method_hir("test", expect![[r#"
fn test:
bb0(v0:BasicObject, v1:BasicObject):
v3:BasicObject = PutSpecialObject VMCore
v3:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
v5:HashExact = NewHash
v7:BasicObject = SendWithoutBlock v3, :core#hash_merge_kwd, v5, v1
v8:BasicObject = PutSpecialObject VMCore
v9:StaticSymbol[VALUE(0x1000)] = Const Value(VALUE(0x1000))
v8:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
v9:StaticSymbol[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v10:Fixnum[1] = Const Value(1)
v12:BasicObject = SendWithoutBlock v8, :core#hash_merge_ptr, v7, v9, v10
SideExit
@ -4374,10 +4379,10 @@ mod tests {
assert_method_hir_with_opcode("test", YARVINSN_putspecialobject, expect![[r#"
fn test:
bb0(v0:BasicObject):
v2:BasicObject = PutSpecialObject VMCore
v2:BasicObject[VMFrozenCore] = Const Value(VALUE(0x1000))
v3:BasicObject = PutSpecialObject CBase
v4:StaticSymbol[VALUE(0x1000)] = Const Value(VALUE(0x1000))
v5:StaticSymbol[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v4:StaticSymbol[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v5:StaticSymbol[VALUE(0x1010)] = Const Value(VALUE(0x1010))
v7:BasicObject = SendWithoutBlock v2, :core#set_method_alias, v3, v4, v5
Return v7
"#]]);

View file

@ -3,6 +3,7 @@ use crate::cruby::{Qfalse, Qnil, Qtrue, VALUE, RUBY_T_ARRAY, RUBY_T_STRING, RUBY
use crate::cruby::{rb_cInteger, rb_cFloat, rb_cArray, rb_cHash, rb_cString, rb_cSymbol, rb_cObject, rb_cTrueClass, rb_cFalseClass, rb_cNilClass, rb_cRange};
use crate::cruby::ClassRelationship;
use crate::cruby::get_class_name;
use crate::cruby::rb_mRubyVMFrozenCore;
use crate::hir::PtrPrintMap;
#[derive(Copy, Clone, Debug, PartialEq)]
@ -68,6 +69,7 @@ fn write_spec(f: &mut std::fmt::Formatter, printer: &TypePrinter) -> std::fmt::R
let ty = printer.inner;
match ty.spec {
Specialization::Any | Specialization::Empty => { Ok(()) },
Specialization::Object(val) if val == unsafe { rb_mRubyVMFrozenCore } => write!(f, "[VMFrozenCore]"),
Specialization::Object(val) => write!(f, "[{}]", val.print(printer.ptr_map)),
Specialization::Type(val) => write!(f, "[class:{}]", get_class_name(val)),
Specialization::TypeExact(val) => write!(f, "[class_exact:{}]", get_class_name(val)),