diff options
-rw-r--r-- | lib/ruby_vm/rjit/insn_compiler.rb | 55 | ||||
-rw-r--r-- | rjit_c.h | 1 | ||||
-rw-r--r-- | rjit_c.rb | 6 | ||||
-rwxr-xr-x | tool/rjit/bindgen.rb | 1 |
4 files changed, 59 insertions, 4 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 5918abbd55..2e05bd6f0c 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -1376,7 +1376,7 @@ module RubyVM::RJIT recv = ctx.stack_opnd(0) comptime_recv = jit.peek_at_stack(0) - if C::RB_TYPE_P(comptime_recv, C::RUBY_T_STRING) + if C.RB_TYPE_P(comptime_recv, C::RUBY_T_STRING) side_exit = side_exit(jit, ctx) jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv, comptime_recv, side_exit) @@ -2464,6 +2464,53 @@ module RubyVM::RJIT # @param jit [RubyVM::RJIT::JITState] # @param ctx [RubyVM::RJIT::Context] # @param asm [RubyVM::RJIT::Assembler] + def jit_rb_kernel_is_a(jit, ctx, asm, argc, known_recv_class) + if argc != 1 + return false + end + + # If this is a super call we might not know the class + if known_recv_class.nil? + return false + end + + # Important note: The output code will simply `return true/false`. + # Correctness follows from: + # - `known_recv_class` implies there is a guard scheduled before here + # for a particular `CLASS_OF(lhs)`. + # - We guard that rhs is identical to the compile-time sample + # - In general, for any two Class instances A, B, `A < B` does not change at runtime. + # Class#superclass is stable. + + sample_rhs = jit.peek_at_stack(0) + sample_lhs = jit.peek_at_stack(1) + + # We are not allowing module here because the module hierachy can change at runtime. + if C.RB_TYPE_P(sample_rhs, C::RUBY_T_CLASS) + return false + end + sample_is_a = C.obj_is_kind_of(sample_lhs, sample_rhs) + + side_exit = side_exit(jit, ctx) + asm.comment('Kernel#is_a?') + asm.mov(:rax, to_value(sample_rhs)) + asm.cmp(ctx.stack_opnd(0), :rax) + asm.jne(counted_exit(side_exit, :send_is_a_class_mismatch)) + + ctx.stack_pop(2) + + stack_ret = ctx.stack_push + if sample_is_a + asm.mov(stack_ret, Qtrue) + else + asm.mov(stack_ret, Qfalse) + end + return true + end + + # @param jit [RubyVM::RJIT::JITState] + # @param ctx [RubyVM::RJIT::Context] + # @param asm [RubyVM::RJIT::Assembler] def jit_rb_obj_not(jit, ctx, asm, argc, _known_recv_class) return false if argc != 0 asm.comment('rb_obj_not') @@ -2710,8 +2757,8 @@ module RubyVM::RJIT register_cfunc_method(NilClass, :nil?, :jit_rb_true) register_cfunc_method(Kernel, :nil?, :jit_rb_false) - #register_cfunc_method(Kernel, :is_a?, :jit_rb_kernel_is_a) - #register_cfunc_method(Kernel, :kind_of?, :jit_rb_kernel_is_a) + register_cfunc_method(Kernel, :is_a?, :jit_rb_kernel_is_a) + register_cfunc_method(Kernel, :kind_of?, :jit_rb_kernel_is_a) #register_cfunc_method(Kernel, :instance_of?, :jit_rb_kernel_instance_of) register_cfunc_method(BasicObject, :==, :jit_rb_obj_equal) @@ -4274,7 +4321,7 @@ module RubyVM::RJIT def dynamic_symbol?(obj) return false if C::SPECIAL_CONST_P(obj) - C::RB_TYPE_P(obj, C::RUBY_T_SYMBOL) + C.RB_TYPE_P(obj, C::RUBY_T_SYMBOL) end def shape_too_complex?(obj) @@ -40,6 +40,7 @@ RJIT_RUNTIME_COUNTERS( send_stackoverflow, send_arity, send_c_tracing, + send_is_a_class_mismatch, send_blockarg_not_nil_or_proxy, send_blockiseq, @@ -306,6 +306,10 @@ module RubyVM::RJIT # :nodoc: all return result; } end + + def obj_is_kind_of(obj, c) + Primitive.cexpr! 'rb_obj_is_kind_of(obj, c)' + end end # @@ -371,6 +375,7 @@ module RubyVM::RJIT # :nodoc: all C::RUBY_SPECIAL_SHIFT = Primitive.cexpr! %q{ SIZET2NUM(RUBY_SPECIAL_SHIFT) } C::RUBY_SYMBOL_FLAG = Primitive.cexpr! %q{ SIZET2NUM(RUBY_SYMBOL_FLAG) } C::RUBY_T_ARRAY = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_ARRAY) } + C::RUBY_T_CLASS = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_CLASS) } C::RUBY_T_ICLASS = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_ICLASS) } C::RUBY_T_MASK = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_MASK) } C::RUBY_T_MODULE = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_MODULE) } @@ -1214,6 +1219,7 @@ module RubyVM::RJIT # :nodoc: all send_stackoverflow: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_stackoverflow)")], send_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_arity)")], send_c_tracing: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_c_tracing)")], + send_is_a_class_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_is_a_class_mismatch)")], send_blockarg_not_nil_or_proxy: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_blockarg_not_nil_or_proxy)")], send_blockiseq: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_blockiseq)")], send_block_handler: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_handler)")], diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index ee2a77446a..8dd69109c5 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -424,6 +424,7 @@ generator = BindingGenerator.new( RUBY_SPECIAL_SHIFT RUBY_SYMBOL_FLAG RUBY_T_ARRAY + RUBY_T_CLASS RUBY_T_ICLASS RUBY_T_MASK RUBY_T_MODULE |