diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2022-08-01 20:06:53 -0700 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2022-08-29 08:47:05 -0700 |
commit | 16307adf8f0cde3a9383e6c7e39fc718ebc89b42 (patch) | |
tree | 3fb3b896cc81531a3ece54771fd2db4f92e27473 | |
parent | 45da6974500070872a2b20fafe2b50bc1dce1052 (diff) | |
download | ruby-16307adf8f0cde3a9383e6c7e39fc718ebc89b42.tar.gz |
Port only ATTRSET of opt_send_without_block (https://github.com/Shopify/ruby/pull/351)
-rw-r--r-- | bootstraptest/test_yjit.rb | 13 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 85 |
2 files changed, 64 insertions, 34 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index d82f3de95e..2f8c6a8f18 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -3074,3 +3074,16 @@ assert_equal 'false', %q{ end function() } + +# opt_send_without_block (VM_METHOD_TYPE_ATTRSET) +assert_equal 'foo', %q{ + class Foo + attr_writer :foo + + def foo() + self.foo = "foo" + end + end + foo = Foo.new + foo.foo +} diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 73d76759a6..ee52800699 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1881,6 +1881,7 @@ pub const OPT_AREF_MAX_CHAIN_DEPTH: i32 = 2; // up to 5 different classes pub const SEND_MAX_DEPTH: i32 = 5; +*/ // Codegen for setting an instance variable. // Preconditions: @@ -1890,13 +1891,13 @@ pub const SEND_MAX_DEPTH: i32 = 5; fn gen_set_ivar( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, recv: VALUE, ivar_name: ID, ) -> CodegenStatus { // Save the PC and SP because the callee may allocate // Note that this modifies REG_SP, which is why we do it first - jit_prepare_routine_call(jit, ctx, cb, REG0); + jit_prepare_routine_call(jit, ctx, asm); // Get the operands from the stack let val_opnd = ctx.stack_pop(1); @@ -1905,17 +1906,22 @@ fn gen_set_ivar( let ivar_index: u32 = unsafe { rb_obj_ensure_iv_index_mapping(recv, ivar_name) }; // Call rb_vm_set_ivar_idx with the receiver, the index of the ivar, and the value - mov(cb, C_ARG_REGS[0], recv_opnd); - mov(cb, C_ARG_REGS[1], imm_opnd(ivar_index.into())); - mov(cb, C_ARG_REGS[2], val_opnd); - call_ptr(cb, REG0, rb_vm_set_ivar_idx as *const u8); + let val = asm.ccall( + rb_vm_set_ivar_idx as *const u8, + vec![ + recv_opnd, + Opnd::Imm(ivar_index.into()), + val_opnd, + ], + ); let out_opnd = ctx.stack_push(Type::Unknown); - mov(cb, out_opnd, RAX); + asm.mov(out_opnd, val); KeepCompiling } +/* // Codegen for getting an instance variable. // Preconditions: // - receiver is in REG0 @@ -3863,6 +3869,7 @@ fn lookup_cfunc_codegen(def: *const rb_method_definition_t) -> Option<MethodGenF CodegenGlobals::look_up_codegen_method(method_serial) } +*/ // Is anyone listening for :c_call and :c_return event currently? fn c_method_tracing_currently_enabled(jit: &JITState) -> bool { @@ -3872,6 +3879,7 @@ fn c_method_tracing_currently_enabled(jit: &JITState) -> bool { } } +/* // Similar to args_kw_argv_to_hash. It is called at runtime from within the // generated assembly to build a Ruby hash of the passed keyword arguments. The // keys are the Symbol objects associated with the keywords and the values are @@ -4798,11 +4806,12 @@ fn gen_struct_aset( jump_to_next_insn(jit, ctx, cb, ocb); EndBlock } +*/ fn gen_send_general( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, ocb: &mut OutlinedCb, cd: *const rb_call_data, block: Option<IseqPtr>, @@ -4824,24 +4833,24 @@ fn gen_send_general( // Don't JIT calls with keyword splat if flags & VM_CALL_KW_SPLAT != 0 { - gen_counter_incr!(cb, send_kw_splat); + gen_counter_incr!(asm, send_kw_splat); return CantCompile; } // Don't JIT calls that aren't simple // Note, not using VM_CALL_ARGS_SIMPLE because sometimes we pass a block. if flags & VM_CALL_ARGS_SPLAT != 0 { - gen_counter_incr!(cb, send_args_splat); + gen_counter_incr!(asm, send_args_splat); return CantCompile; } if flags & VM_CALL_ARGS_BLOCKARG != 0 { - gen_counter_incr!(cb, send_block_arg); + gen_counter_incr!(asm, send_block_arg); return CantCompile; } // Defer compilation so we can specialize on class of receiver if !jit_at_current_insn(jit) { - defer_compilation(jit, ctx, cb, ocb); + defer_compilation(jit, ctx, asm, ocb); return EndBlock; } @@ -4854,6 +4863,8 @@ fn gen_send_general( // Points to the receiver operand on the stack let recv = ctx.stack_opnd(argc); let recv_opnd = StackOpnd(argc.try_into().unwrap()); + // TODO: Resurrect this once jit_guard_known_klass is implemented for getivar + /* mov(cb, REG0, recv); jit_guard_known_klass( jit, @@ -4865,7 +4876,7 @@ fn gen_send_general( comptime_recv, SEND_MAX_DEPTH, side_exit, - ); + ); */ // Do method lookup let mut cme = unsafe { rb_callable_method_entry(comptime_recv_klass, mid) }; @@ -4891,7 +4902,7 @@ fn gen_send_general( if flags & VM_CALL_FCALL == 0 { // otherwise we need an ancestry check to ensure the receiver is vaild to be called // as protected - jit_protected_callee_ancestry_guard(jit, cb, ocb, cme, side_exit); + return CantCompile; // jit_protected_callee_ancestry_guard(jit, cb, ocb, cme, side_exit); } } _ => { @@ -4908,25 +4919,26 @@ fn gen_send_general( let def_type = unsafe { get_cme_def_type(cme) }; match def_type { VM_METHOD_TYPE_ISEQ => { - return gen_send_iseq(jit, ctx, cb, ocb, ci, cme, block, argc); + return CantCompile; // return gen_send_iseq(jit, ctx, cb, ocb, ci, cme, block, argc); } VM_METHOD_TYPE_CFUNC => { + return CantCompile; /* return gen_send_cfunc( jit, ctx, - cb, + asm, ocb, ci, cme, block, argc, &comptime_recv_klass, - ); + ); */ } VM_METHOD_TYPE_IVAR => { if argc != 0 { // Argument count mismatch. Getters take no arguments. - gen_counter_incr!(cb, send_getter_arity); + gen_counter_incr!(asm, send_getter_arity); return CantCompile; } @@ -4940,10 +4952,11 @@ fn gen_send_general( // attr_accessor is invalidated and we exit at the closest // instruction boundary which is always outside of the body of // the attr_accessor code. - gen_counter_incr!(cb, send_cfunc_tracing); + gen_counter_incr!(asm, send_cfunc_tracing); return CantCompile; } + return CantCompile; /* mov(cb, REG0, recv); let ivar_name = unsafe { get_cme_def_body_attr_id(cme) }; @@ -4958,31 +4971,32 @@ fn gen_send_general( recv_opnd, side_exit, ); + */ } VM_METHOD_TYPE_ATTRSET => { if flags & VM_CALL_KWARG != 0 { - gen_counter_incr!(cb, send_attrset_kwargs); + gen_counter_incr!(asm, send_attrset_kwargs); return CantCompile; } else if argc != 1 || unsafe { !RB_TYPE_P(comptime_recv, RUBY_T_OBJECT) } { - gen_counter_incr!(cb, send_ivar_set_method); + gen_counter_incr!(asm, send_ivar_set_method); return CantCompile; } else if c_method_tracing_currently_enabled(jit) { // Can't generate code for firing c_call and c_return events // See :attr-tracing: - gen_counter_incr!(cb, send_cfunc_tracing); + gen_counter_incr!(asm, send_cfunc_tracing); return CantCompile; } else { let ivar_name = unsafe { get_cme_def_body_attr_id(cme) }; - return gen_set_ivar(jit, ctx, cb, comptime_recv, ivar_name); + return gen_set_ivar(jit, ctx, asm, comptime_recv, ivar_name); } } // Block method, e.g. define_method(:foo) { :my_block } VM_METHOD_TYPE_BMETHOD => { - gen_counter_incr!(cb, send_bmethod); + gen_counter_incr!(asm, send_bmethod); return CantCompile; } VM_METHOD_TYPE_ZSUPER => { - gen_counter_incr!(cb, send_zsuper_method); + gen_counter_incr!(asm, send_zsuper_method); return CantCompile; } VM_METHOD_TYPE_ALIAS => { @@ -4991,15 +5005,16 @@ fn gen_send_general( continue; } VM_METHOD_TYPE_UNDEF => { - gen_counter_incr!(cb, send_undef_method); + gen_counter_incr!(asm, send_undef_method); return CantCompile; } VM_METHOD_TYPE_NOTIMPLEMENTED => { - gen_counter_incr!(cb, send_not_implemented_method); + gen_counter_incr!(asm, send_not_implemented_method); return CantCompile; } // Send family of methods, e.g. call/apply VM_METHOD_TYPE_OPTIMIZED => { + return CantCompile; /* let opt_type = unsafe { get_cme_def_body_optimized_type(cme) }; match opt_type { OPTIMIZED_METHOD_TYPE_SEND => { @@ -5042,13 +5057,14 @@ fn gen_send_general( panic!("unknown optimized method type!") } } + */ } VM_METHOD_TYPE_MISSING => { - gen_counter_incr!(cb, send_missing_method); + gen_counter_incr!(asm, send_missing_method); return CantCompile; } VM_METHOD_TYPE_REFINED => { - gen_counter_incr!(cb, send_refined_method); + gen_counter_incr!(asm, send_refined_method); return CantCompile; } _ => { @@ -5061,23 +5077,24 @@ fn gen_send_general( fn gen_opt_send_without_block( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, ocb: &mut OutlinedCb, ) -> CodegenStatus { let cd = jit_get_arg(jit, 0).as_ptr(); - gen_send_general(jit, ctx, cb, ocb, cd, None) + gen_send_general(jit, ctx, asm, ocb, cd, None) } +/* fn gen_send( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, ocb: &mut OutlinedCb, ) -> CodegenStatus { let cd = jit_get_arg(jit, 0).as_ptr(); let block = jit_get_arg(jit, 1).as_optional_ptr(); - return gen_send_general(jit, ctx, cb, ocb, cd, block); + return gen_send_general(jit, ctx, asm, ocb, cd, block); } fn gen_invokesuper( @@ -6028,7 +6045,7 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { //YARVINSN_getblockparamproxy => Some(gen_getblockparamproxy), //YARVINSN_getblockparam => Some(gen_getblockparam), - //YARVINSN_opt_send_without_block => Some(gen_opt_send_without_block), + YARVINSN_opt_send_without_block => Some(gen_opt_send_without_block), //YARVINSN_send => Some(gen_send), //YARVINSN_invokesuper => Some(gen_invokesuper), YARVINSN_leave => Some(gen_leave), |