summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb53
-rw-r--r--mjit_c.h7
-rw-r--r--mjit_c.rb30
-rwxr-xr-xtool/mjit/bindgen.rb3
4 files changed, 76 insertions, 17 deletions
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb
index 2606f84c6c..8553f644a6 100644
--- a/lib/ruby_vm/mjit/insn_compiler.rb
+++ b/lib/ruby_vm/mjit/insn_compiler.rb
@@ -859,7 +859,7 @@ module RubyVM::MJIT
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
- def jit_getivar(jit, ctx, asm, comptime_obj, ivar_id)
+ def jit_getivar(jit, ctx, asm, comptime_obj, ivar_id, obj_opnd = nil)
side_exit = side_exit(jit, ctx)
starting_ctx = ctx.dup # copy for jit_chain_guard
@@ -868,7 +868,11 @@ module RubyVM::MJIT
asm.incr_counter(:getivar_special_const)
return CantCompile
end
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)])
+ if obj_opnd.nil? # getivar
+ asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)])
+ else # attr_reader
+ asm.mov(:rax, obj_opnd)
+ end
guard_object_is_heap(asm, :rax, counted_exit(side_exit, :getivar_not_heap))
case C.BUILTIN_TYPE(comptime_obj)
@@ -891,7 +895,7 @@ module RubyVM::MJIT
index = C.rb_shape_get_iv_index(shape_id, ivar_id)
if index
- # See ROBJECT_IVPTR
+ asm.comment('ROBJECT_IVPTR')
if C.FL_TEST_RAW(comptime_obj, C.ROBJECT_EMBED)
# Access embedded array
asm.mov(:rax, [:rax, C.RObject.offsetof(:as, :ary) + (index * C.VALUE.size)])
@@ -906,6 +910,9 @@ module RubyVM::MJIT
val_opnd = Qnil
end
+ if obj_opnd
+ ctx.stack_pop # pop receiver for attr_reader
+ end
stack_opnd = ctx.stack_push
asm.mov(stack_opnd, val_opnd)
@@ -981,14 +988,14 @@ module RubyVM::MJIT
# Invalidate on redefinition (part of vm_search_method_fastpath)
@invariants.assume_method_lookup_stable(jit, cme)
- jit_call_method_each_type(jit, ctx, asm, ci, argc, flags, cme)
+ jit_call_method_each_type(jit, ctx, asm, ci, argc, flags, cme, comptime_recv, recv_opnd)
end
# vm_call_method_each_type
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
- def jit_call_method_each_type(jit, ctx, asm, ci, argc, flags, cme)
+ def jit_call_method_each_type(jit, ctx, asm, ci, argc, flags, cme, comptime_recv, recv_opnd)
case cme.def.type
when C.VM_METHOD_TYPE_ISEQ
jit_call_iseq_setup(jit, ctx, asm, ci, cme, flags, argc)
@@ -1000,8 +1007,7 @@ module RubyVM::MJIT
asm.incr_counter(:send_attrset)
return CantCompile
when C.VM_METHOD_TYPE_IVAR
- asm.incr_counter(:send_ivar)
- return CantCompile
+ jit_call_ivar(jit, ctx, asm, ci, cme, flags, argc, comptime_recv, recv_opnd)
# when C.VM_METHOD_TYPE_MISSING
when C.VM_METHOD_TYPE_BMETHOD
asm.incr_counter(:send_bmethod)
@@ -1046,6 +1052,9 @@ module RubyVM::MJIT
end
# vm_call_iseq_setup_normal (vm_call_iseq_setup_2 -> vm_call_iseq_setup_normal)
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
def jit_call_iseq_setup_normal(jit, ctx, asm, ci, cme, flags, argc, iseq)
# Save caller SP and PC before pushing a callee frame for backtrace and side exits
asm.comment('save SP to caller CFP')
@@ -1062,6 +1071,36 @@ module RubyVM::MJIT
jit_push_frame(jit, ctx, asm, ci, cme, flags, argc, iseq, frame_type, next_pc)
end
+ # vm_call_ivar
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def jit_call_ivar(jit, ctx, asm, ci, cme, flags, argc, comptime_recv, recv_opnd)
+ if flags & C.VM_CALL_ARGS_SPLAT != 0
+ asm.incr_counter(:send_ivar_splat)
+ return CantCompile
+ end
+
+ if argc != 0
+ asm.incr_counter(:send_ivar_arity)
+ return CantCompile
+ end
+
+ if flags & C.VM_CALL_OPT_SEND != 0
+ asm.incr_counter(:send_ivar_opt_send)
+ return CantCompile
+ end
+
+ ivar_id = cme.def.body.attr.id
+
+ if flags & C.VM_CALL_OPT_SEND != 0
+ asm.incr_counter(:send_ivar_blockarg)
+ return CantCompile
+ end
+
+ jit_getivar(jit, ctx, asm, comptime_recv, ivar_id, recv_opnd)
+ end
+
# vm_push_frame
#
# Frame structure:
diff --git a/mjit_c.h b/mjit_c.h
index 20f4c0bf90..659701d038 100644
--- a/mjit_c.h
+++ b/mjit_c.h
@@ -119,7 +119,6 @@ MJIT_RUNTIME_COUNTERS(
send_tailcall,
send_not_implemented_type,
send_cfunc,
- send_ivar,
send_attrset,
send_bmethod,
send_alias,
@@ -127,6 +126,12 @@ MJIT_RUNTIME_COUNTERS(
send_zsuper,
send_refined,
+ send_ivar,
+ send_ivar_splat,
+ send_ivar_arity,
+ send_ivar_opt_send,
+ send_ivar_blockarg,
+
send_guard_nil,
send_guard_true,
send_guard_false,
diff --git a/mjit_c.rb b/mjit_c.rb
index c5220561ee..21c2a0c840 100644
--- a/mjit_c.rb
+++ b/mjit_c.rb
@@ -395,6 +395,10 @@ module RubyVM::MJIT # :nodoc: all
Primitive.cexpr! %q{ UINT2NUM(VM_CALL_KW_SPLAT_bit) }
end
+ def C.VM_CALL_OPT_SEND
+ Primitive.cexpr! %q{ UINT2NUM(VM_CALL_OPT_SEND) }
+ end
+
def C.VM_CALL_TAILCALL
Primitive.cexpr! %q{ UINT2NUM(VM_CALL_TAILCALL) }
end
@@ -499,6 +503,10 @@ module RubyVM::MJIT # :nodoc: all
@IC ||= self.iseq_inline_constant_cache
end
+ def C.ID
+ @ID ||= CType::Immediate.parse("unsigned long")
+ end
+
def C.IVC
@IVC ||= self.iseq_inline_iv_cache_entry
end
@@ -856,6 +864,14 @@ module RubyVM::MJIT # :nodoc: all
@rb_iseq_t ||= self.rb_iseq_struct
end
+ def C.rb_method_attr_t
+ @rb_method_attr_t ||= CType::Struct.new(
+ "rb_method_attr_struct", Primitive.cexpr!("SIZEOF(struct rb_method_attr_struct)"),
+ id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_attr_struct *)NULL)), id)")],
+ location: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_attr_struct *)NULL)), location)")],
+ )
+ end
+
def C.rb_method_definition_struct
@rb_method_definition_struct ||= CType::Struct.new(
"rb_method_definition_struct", Primitive.cexpr!("SIZEOF(struct rb_method_definition_struct)"),
@@ -917,13 +933,17 @@ module RubyVM::MJIT # :nodoc: all
send_tailcall: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_tailcall)")],
send_not_implemented_type: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_not_implemented_type)")],
send_cfunc: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_cfunc)")],
- send_ivar: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar)")],
send_attrset: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_attrset)")],
send_bmethod: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_bmethod)")],
send_alias: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_alias)")],
send_optimized: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_optimized)")],
send_zsuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_zsuper)")],
send_refined: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_refined)")],
+ send_ivar: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar)")],
+ send_ivar_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar_splat)")],
+ send_ivar_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar_arity)")],
+ send_ivar_opt_send: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar_opt_send)")],
+ send_ivar_blockarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_ivar_blockarg)")],
send_guard_nil: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_guard_nil)")],
send_guard_true: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_guard_true)")],
send_guard_false: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_mjit_runtime_counters *)NULL)), send_guard_false)")],
@@ -996,10 +1016,6 @@ module RubyVM::MJIT # :nodoc: all
CType::Bool.new
end
- def C.ID
- CType::Stub.new(:ID)
- end
-
def C.rb_thread_struct
CType::Stub.new(:rb_thread_struct)
end
@@ -1088,10 +1104,6 @@ module RubyVM::MJIT # :nodoc: all
CType::Stub.new(:rb_method_cfunc_t)
end
- def C.rb_method_attr_t
- CType::Stub.new(:rb_method_attr_t)
- end
-
def C.rb_method_alias_t
CType::Stub.new(:rb_method_alias_t)
end
diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb
index 2c4fef82d9..0d8cdee83f 100755
--- a/tool/mjit/bindgen.rb
+++ b/tool/mjit/bindgen.rb
@@ -376,6 +376,7 @@ generator = BindingGenerator.new(
VM_CALL_KW_SPLAT_bit
VM_CALL_TAILCALL
VM_CALL_TAILCALL_bit
+ VM_CALL_OPT_SEND
VM_ENV_FLAG_LOCAL
VM_FRAME_MAGIC_METHOD
VM_METHOD_TYPE_CFUNC
@@ -407,6 +408,7 @@ generator = BindingGenerator.new(
types: %w[
CALL_DATA
IC
+ ID
IVC
RB_BUILTIN
RBasic
@@ -442,6 +444,7 @@ generator = BindingGenerator.new(
rb_serial_t
rb_shape
rb_shape_t
+ rb_method_attr_t
],
dynamic_types: %w[
VALUE