Skip to content

Commit

Permalink
RJIT: Implement putspecialobject insn
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun committed Mar 18, 2023
1 parent 2c8f287 commit 93e05aa
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 12 deletions.
41 changes: 29 additions & 12 deletions lib/ruby_vm/rjit/insn_compiler.rb
Expand Up @@ -18,7 +18,7 @@ def compile(jit, ctx, asm, insn)
asm.incr_counter(:rjit_insns_count)
asm.comment("Insn: #{insn.name}")

# 75/102
# 76/102
case insn.name
when :nop then nop(jit, ctx, asm)
when :getlocal then getlocal(jit, ctx, asm)
Expand All @@ -40,7 +40,7 @@ def compile(jit, ctx, asm, insn)
when :putnil then putnil(jit, ctx, asm)
when :putself then putself(jit, ctx, asm)
when :putobject then putobject(jit, ctx, asm)
# putspecialobject
when :putspecialobject then putspecialobject(jit, ctx, asm)
when :putstring then putstring(jit, ctx, asm)
when :concatstrings then concatstrings(jit, ctx, asm)
when :anytostring then anytostring(jit, ctx, asm)
Expand Down Expand Up @@ -621,7 +621,22 @@ def putobject(jit, ctx, asm, val: jit.operand(0))
KeepCompiling
end

# putspecialobject
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
def putspecialobject(jit, ctx, asm)
object_type = jit.operand(0)
if object_type == C::VM_SPECIAL_OBJECT_VMCORE
stack_top = ctx.stack_push
asm.mov(:rax, C.rb_mRubyVMFrozenCore)
asm.mov(stack_top, :rax)
KeepCompiling
else
# TODO: implement for VM_SPECIAL_OBJECT_CBASE and
# VM_SPECIAL_OBJECT_CONST_BASE
CantCompile
end
end

# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
Expand Down Expand Up @@ -2623,39 +2638,41 @@ def jit_guard_known_klass(jit, ctx, asm, known_klass, obj_opnd, comptime_obj, si
# Only memory operand is supported for now
assert_equal(true, obj_opnd.is_a?(Array))

if known_klass == NilClass
# Touching this as Ruby could crash for FrozenCore
known_klass = C.to_value(known_klass)
if known_klass == C.rb_cNilClass
asm.comment('guard object is nil')
asm.cmp(obj_opnd, Qnil)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
elsif known_klass == TrueClass
elsif known_klass == C.rb_cTrueClass
asm.comment('guard object is true')
asm.cmp(obj_opnd, Qtrue)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
elsif known_klass == FalseClass
elsif known_klass == C.rb_cFalseClass
asm.comment('guard object is false')
asm.cmp(obj_opnd, Qfalse)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
elsif known_klass == Integer && fixnum?(comptime_obj)
elsif known_klass == C.rb_cInteger && fixnum?(comptime_obj)
asm.comment('guard object is fixnum')
asm.test(obj_opnd, C::RUBY_FIXNUM_FLAG)
jit_chain_guard(:jz, jit, ctx, asm, side_exit, limit:)
elsif known_klass == Symbol && static_symbol?(comptime_obj)
elsif known_klass == C.rb_cSymbol && static_symbol?(comptime_obj)
# We will guard STATIC vs DYNAMIC as though they were separate classes
# DYNAMIC symbols can be handled by the general else case below
asm.comment('guard object is static symbol')
assert_equal(8, C::RUBY_SPECIAL_SHIFT)
asm.cmp(BytePtr[*obj_opnd], C::RUBY_SYMBOL_FLAG)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
elsif known_klass == Float && flonum?(comptime_obj)
elsif known_klass == C.rb_cFloat && flonum?(comptime_obj)
# We will guard flonum vs heap float as though they were separate classes
asm.comment('guard object is flonum')
asm.mov(:rax, obj_opnd)
asm.and(:rax, C::RUBY_FLONUM_MASK)
asm.cmp(:rax, C::RUBY_FLONUM_FLAG)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
elsif C::FL_TEST(known_klass, C::RUBY_FL_SINGLETON) && comptime_obj == C.rb_class_attached_object(known_klass)
elsif C.FL_TEST(known_klass, C::RUBY_FL_SINGLETON) && comptime_obj == C.rb_class_attached_object(known_klass)
asm.comment('guard known object with singleton class')
asm.mov(:rax, C.to_value(comptime_obj))
asm.mov(:rax, to_value(comptime_obj))
asm.cmp(obj_opnd, :rax)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
else
Expand All @@ -2674,7 +2691,7 @@ def jit_guard_known_klass(jit, ctx, asm, known_klass, obj_opnd, comptime_obj, si
# Bail if receiver class is different from known_klass
klass_opnd = [obj_opnd, C.RBasic.offsetof(:klass)]
asm.comment("guard known class #{known_klass}")
asm.mov(:rcx, to_value(known_klass))
asm.mov(:rcx, known_klass)
asm.cmp(klass_opnd, :rcx)
jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
end
Expand Down
5 changes: 5 additions & 0 deletions rjit_c.rb
Expand Up @@ -403,6 +403,7 @@ def rb_iseqw_to_iseq(iseqw)
C::VM_METHOD_TYPE_REFINED = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_REFINED) }
C::VM_METHOD_TYPE_UNDEF = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_UNDEF) }
C::VM_METHOD_TYPE_ZSUPER = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_ZSUPER) }
C::VM_SPECIAL_OBJECT_VMCORE = Primitive.cexpr! %q{ SIZET2NUM(VM_SPECIAL_OBJECT_VMCORE) }

def C.block_type_iseq
Primitive.cexpr! %q{ SIZET2NUM(block_type_iseq) }
Expand Down Expand Up @@ -440,6 +441,10 @@ def C.rb_cTrueClass
Primitive.cexpr! %q{ SIZET2NUM(rb_cTrueClass) }
end

def C.rb_mRubyVMFrozenCore
Primitive.cexpr! %q{ SIZET2NUM(rb_mRubyVMFrozenCore) }
end

def C.rb_rjit_global_events
Primitive.cexpr! %q{ SIZET2NUM(rb_rjit_global_events) }
end
Expand Down
2 changes: 2 additions & 0 deletions tool/rjit/bindgen.rb
Expand Up @@ -460,6 +460,7 @@ def push_target(target)
VM_METHOD_TYPE_REFINED
VM_METHOD_TYPE_UNDEF
VM_METHOD_TYPE_ZSUPER
VM_SPECIAL_OBJECT_VMCORE
],
},
values: {
Expand All @@ -474,6 +475,7 @@ def push_target(target)
rb_cSymbol
rb_cTrueClass
rb_rjit_global_events
rb_mRubyVMFrozenCore
],
},
funcs: %w[
Expand Down

0 comments on commit 93e05aa

Please sign in to comment.