@@ -2144,6 +2144,33 @@ def jit_rb_obj_not_equal(jit, ctx, asm, argc, _known_recv_class)
21442144 jit_equality_specialized ( jit , ctx , asm , false )
21452145 end
21462146
2147+ # @param jit [RubyVM::MJIT::JITState]
2148+ # @param ctx [RubyVM::MJIT::Context]
2149+ # @param asm [RubyVM::MJIT::Assembler]
2150+ def jit_rb_mod_eqq ( jit , ctx , asm , argc , _known_recv_class )
2151+ return false if argc != 1
2152+
2153+ asm . comment ( 'Module#===' )
2154+ # By being here, we know that the receiver is a T_MODULE or a T_CLASS, because Module#=== can
2155+ # only live on these objects. With that, we can call rb_obj_is_kind_of() without
2156+ # jit_prepare_routine_call() or a control frame push because it can't raise, allocate, or call
2157+ # Ruby methods with these inputs.
2158+ # Note the difference in approach from Kernel#is_a? because we don't get a free guard for the
2159+ # right hand side.
2160+ lhs = ctx . stack_opnd ( 1 ) # the module
2161+ rhs = ctx . stack_opnd ( 0 )
2162+ asm . mov ( C_ARGS [ 0 ] , rhs ) ;
2163+ asm . mov ( C_ARGS [ 1 ] , lhs ) ;
2164+ asm . call ( C . rb_obj_is_kind_of )
2165+
2166+ # Return the result
2167+ ctx . stack_pop ( 2 )
2168+ stack_ret = ctx . stack_push
2169+ asm . mov ( stack_ret , C_RET )
2170+
2171+ return true
2172+ end
2173+
21472174 # @param jit [RubyVM::MJIT::JITState]
21482175 # @param ctx [RubyVM::MJIT::Context]
21492176 # @param asm [RubyVM::MJIT::Assembler]
@@ -2309,7 +2336,7 @@ def register_cfunc_codegen_funcs
23092336 register_cfunc_method ( BasicObject , :!= , :jit_rb_obj_not_equal )
23102337 register_cfunc_method ( Kernel , :eql? , :jit_rb_obj_equal )
23112338 register_cfunc_method ( Module , :== , :jit_rb_obj_equal )
2312- # register_cfunc_method(Module, :===, :jit_rb_mod_eqq)
2339+ register_cfunc_method ( Module , :=== , :jit_rb_mod_eqq )
23132340 register_cfunc_method ( Symbol , :== , :jit_rb_obj_equal )
23142341 register_cfunc_method ( Symbol , :=== , :jit_rb_obj_equal )
23152342 register_cfunc_method ( Integer , :== , :jit_rb_int_equal )
0 commit comments