Skip to content

Commit

Permalink
Optimize BasicObject#!
Browse files Browse the repository at this point in the history
  • Loading branch information
k0kubun committed Mar 6, 2023
1 parent e8a36eb commit db4a8af
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
52 changes: 52 additions & 0 deletions lib/ruby_vm/mjit/insn_compiler.rb
Expand Up @@ -11,6 +11,8 @@ def initialize(cb, ocb, exit_compiler)
@ocb.write(asm)
end

@cfunc_codegen_table = {}
register_cfunc_codegen_funcs
# freeze # workaround a binding.irb issue. TODO: resurrect this
end

Expand Down Expand Up @@ -1675,10 +1677,49 @@ def putobject_INT2FIX_1_(jit, ctx, asm)
putobject(jit, ctx, asm, val: C.to_value(1))
end

#
# C func
#

# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]
# @param asm [RubyVM::MJIT::Assembler]
def jit_rb_obj_not(jit, ctx, asm)
recv = ctx.stack_pop
# This `test` sets ZF only for Qnil and Qfalse, which let cmovz set.
asm.test(recv, ~Qnil)
asm.mov(:rax, Qfalse)
asm.mov(:rcx, Qtrue)
asm.cmovz(:rax, :rcx)
asm.mov(ctx.stack_push, :rax)

true
end

#
# Helpers
#

def register_cfunc_codegen_funcs
register_cfunc_method(BasicObject, '!', :jit_rb_obj_not)
end

def register_cfunc_method(klass, mid_str, func)
mid = C.rb_intern(mid_str)
me = C.rb_method_entry_at(klass, mid)

assert_equal(false, me.nil?)

# Only cfuncs are supported
method_serial = me.def.method_serial

@cfunc_codegen_table[method_serial] = method(func)
end

def lookup_cfunc_codegen(cme_def)
@cfunc_codegen_table[cme_def.method_serial]
end

def jit_getlocal_generic(jit, ctx, asm, idx:, level:)
# Load environment pointer EP at level
ep_reg = :rax
Expand Down Expand Up @@ -2545,6 +2586,17 @@ def jit_call_cfunc_with_frame(jit, ctx, asm, cme, flags, argc, block_handler, se
return CantCompile
end

# Delegate to codegen for C methods if we have it.
if flags & C.VM_CALL_KWARG == 0 && flags & C.VM_CALL_OPT_SEND == 0
known_cfunc_codegen = lookup_cfunc_codegen(cme.def)
if known_cfunc_codegen&.call(jit, ctx, asm)
# cfunc codegen generated code. Terminate the block so
# there isn't multiple calls in the same block.
jump_to_next_insn(jit, ctx, asm)
return EndBlock
end
end

# We will not have side exits from here. Adjust the stack.
if flags & C.VM_CALL_OPT_SEND != 0
jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
Expand Down
20 changes: 20 additions & 0 deletions mjit_c.rb
Expand Up @@ -269,6 +269,15 @@ def rb_obj_frozen_p(obj)
Primitive.cexpr! 'rb_obj_frozen_p(obj)'
end

def rb_intern(str)
Primitive.cexpr! 'SIZET2NUM((size_t)rb_intern(RSTRING_PTR(str)))'
end

def rb_method_entry_at(klass, mid)
me_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_method_entry_at(klass, (ID)NUM2SIZET(mid)))'
me_addr == 0 ? nil : rb_method_entry_t.new(me_addr)
end

#========================================================================================
#
# Old stuff
Expand Down Expand Up @@ -1235,6 +1244,17 @@ def C.rb_method_definition_struct
)
end

def C.rb_method_entry_t
@rb_method_entry_t ||= CType::Struct.new(
"rb_method_entry_struct", Primitive.cexpr!("SIZEOF(struct rb_method_entry_struct)"),
flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), flags)")],
defined_class: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), defined_class)")],
def: [CType::Pointer.new { self.rb_method_definition_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), def)")],
called_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), called_id)")],
owner: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), owner)")],
)
end

def C.rb_method_iseq_t
@rb_method_iseq_t ||= CType::Struct.new(
"rb_method_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_method_iseq_struct)"),
Expand Down
1 change: 1 addition & 0 deletions tool/mjit/bindgen.rb
Expand Up @@ -471,6 +471,7 @@ def push_target(target)
rb_call_data
rb_callable_method_entry_struct
rb_callable_method_entry_t
rb_method_entry_t
rb_callcache
rb_callinfo
rb_control_frame_t
Expand Down

0 comments on commit db4a8af

Please sign in to comment.