ruby-changes:73266
From: Takashi <ko1@a...>
Date: Tue, 30 Aug 2022 01:05:16 +0900 (JST)
Subject: [ruby-changes:73266] 726a451955 (master): Port invokebuiltin* insns to the new backend IR (https://github.com/Shopify/ruby/pull/375)
https://git.ruby-lang.org/ruby.git/commit/?id=726a451955 From 726a4519550fd9191833e482122e3c7bf9a468be Mon Sep 17 00:00:00 2001 From: Takashi Kokubun <takashikkbn@g...> Date: Mon, 8 Aug 2022 08:27:54 -0700 Subject: Port invokebuiltin* insns to the new backend IR (https://github.com/Shopify/ruby/pull/375) * Port invokebuiltin* insns to the new backend IR * Fix the C_ARG_OPNDS check boundary --- bootstraptest/test_yjit.rb | 22 ++++++++++++++ yjit/src/backend/arm64/mod.rs | 2 +- yjit/src/backend/x86_64/mod.rs | 2 +- yjit/src/codegen.rs | 65 ++++++++++++++++-------------------------- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 826e0066fa..0f9150e388 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -3143,3 +3143,25 @@ assert_equal '["a", "b"]', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L3143 end foo } + +# invokebuiltin +assert_equal '123', %q{ + def foo(obj) + obj.foo = 123 + end + + struct = Struct.new(:foo) + obj = struct.new + foo(obj) +} + +# invokebuiltin_delegate +assert_equal '.', %q{ + def foo(path) + Dir.open(path).path + end + foo(".") +} + +# opt_invokebuiltin_delegate_leave +assert_equal '[0]', %q{"\x00".unpack("c")} diff --git a/yjit/src/backend/arm64/mod.rs b/yjit/src/backend/arm64/mod.rs index 2e8c2068af..d6e8e831c7 100644 --- a/yjit/src/backend/arm64/mod.rs +++ b/yjit/src/backend/arm64/mod.rs @@ -196,7 +196,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/arm64/mod.rs#L196 } }, Op::CCall => { - assert!(opnds.len() < C_ARG_OPNDS.len()); + assert!(opnds.len() <= C_ARG_OPNDS.len()); // For each of the operands we're going to first load them // into a register and then move them into the correct diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index 4ba849b239..b0802b3187 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -400,7 +400,7 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/x86_64/mod.rs#L400 // C function call Op::CCall => { // Temporary - assert!(insn.opnds.len() < _C_ARG_OPNDS.len()); + assert!(insn.opnds.len() <= _C_ARG_OPNDS.len()); // For each operand for (idx, opnd) in insn.opnds.iter().enumerate() { diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 78120a5995..7f95512445 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5818,45 +5818,40 @@ fn gen_getblockparam( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5818 KeepCompiling } +*/ fn gen_invokebuiltin( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { let bf: *const rb_builtin_function = jit_get_arg(jit, 0).as_ptr(); let bf_argc: usize = unsafe { (*bf).argc }.try_into().expect("non negative argc"); // ec, self, and arguments - if bf_argc + 2 > C_ARG_REGS.len() { + if bf_argc + 2 > C_ARG_OPNDS.len() { return CantCompile; } // If the calls don't allocate, do they need up to date PC, SP? - jit_prepare_routine_call(jit, ctx, cb, REG0); + jit_prepare_routine_call(jit, ctx, asm); // Call the builtin func (ec, recv, arg1, arg2, ...) - mov(cb, C_ARG_REGS[0], REG_EC); - mov( - cb, - C_ARG_REGS[1], - mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_SELF), - ); + let mut args = vec![EC, Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF)]; // Copy arguments from locals for i in 0..bf_argc { let stack_opnd = ctx.stack_opnd((bf_argc - i - 1) as i32); - let c_arg_reg = C_ARG_REGS[2 + i]; - mov(cb, c_arg_reg, stack_opnd); + args.push(stack_opnd); } - call_ptr(cb, REG0, unsafe { (*bf).func_ptr } as *const u8); + let val = asm.ccall(unsafe { (*bf).func_ptr } as *const u8, args); // Push the return value ctx.stack_pop(bf_argc); let stack_ret = ctx.stack_push(Type::Unknown); - mov(cb, stack_ret, RAX); + asm.mov(stack_ret, val); KeepCompiling } @@ -5867,7 +5862,7 @@ fn gen_invokebuiltin( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5862 fn gen_opt_invokebuiltin_delegate( jit: &mut JITState, ctx: &mut Context, - cb: &mut CodeBlock, + asm: &mut Assembler, _ocb: &mut OutlinedCb, ) -> CodegenStatus { let bf: *const rb_builtin_function = jit_get_arg(jit, 0).as_ptr(); @@ -5875,44 +5870,36 @@ fn gen_opt_invokebuiltin_delegate( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5870 let start_index = jit_get_arg(jit, 1).as_i32(); // ec, self, and arguments - if bf_argc + 2 > (C_ARG_REGS.len() as i32) { + if bf_argc + 2 > (C_ARG_OPNDS.len() as i32) { return CantCompile; } // If the calls don't allocate, do they need up to date PC, SP? - jit_prepare_routine_call(jit, ctx, cb, REG0); - - if bf_argc > 0 { - // Load environment pointer EP from CFP - mov(cb, REG0, mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_EP)); - } + jit_prepare_routine_call(jit, ctx, asm); // Call the builtin func (ec, recv, arg1, arg2, ...) - mov(cb, C_ARG_REGS[0], REG_EC); - mov( - cb, - C_ARG_REGS[1], - mem_opnd(64, REG_CFP, RUBY_OFFSET_CFP_SELF), - ); + let mut args = vec![EC, Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF)]; // Copy arguments from locals - for i in 0..bf_argc { - let table_size = unsafe { get_iseq_body_local_table_size(jit.iseq) }; - let offs: i32 = -(table_size as i32) - (VM_ENV_DATA_SIZE as i32) + 1 + start_index + i; - let local_opnd = mem_opnd(64, REG0, offs * (SIZEOF_VALUE as i32)); - let offs: usize = (i + 2) as usize; - let c_arg_reg = C_ARG_REGS[offs]; - mov(cb, c_arg_reg, local_opnd); + if bf_argc > 0 { + // Load environment pointer EP from CFP + let ep = asm.load(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP)); + + for i in 0..bf_argc { + let table_size = unsafe { get_iseq_body_local_table_size(jit.iseq) }; + let offs: i32 = -(table_size as i32) - (VM_ENV_DATA_SIZE as i32) + 1 + start_index + i; + let local_opnd = Opnd::mem(64, ep, offs * (SIZEOF_VALUE as i32)); + args.push(local_opnd); + } } - call_ptr(cb, REG0, unsafe { (*bf).func_ptr } as *const u8); + let val = asm.ccall(unsafe { (*bf).func_ptr } as *const u8, args); // Push the return value let stack_ret = ctx.stack_push(Type::Unknown); - mov(cb, stack_ret, RAX); + asm.mov(stack_ret, val); KeepCompiling } -*/ /// Maps a YARV opcode to a code generation function (if supported) fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { @@ -5982,12 +5969,10 @@ fn get_gen_fn(opcode: VALUE) -> Option<InsnGenFn> { https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L5969 YARVINSN_opt_size => Some(gen_opt_size), YARVINSN_opt_length => Some(gen_opt_length), YARVINSN_opt_regexpmatch2 => Some(gen_opt_regexpmatch2), - /* - YARVINSN_opt_getinlinecache => Some(gen_opt_getinlinecache), + //YARVINSN_opt_getinlinecache => Some(gen_opt_getinlinecache), YARVINSN_invokebuiltin => Some(gen_invokebuiltin), YARVINSN_opt_invokebuiltin_delegate => Some(gen_opt_invokebuiltin_delegate), YARVINSN_opt_invokebuiltin_delegate_leave => Some(gen_opt_invokebuiltin_delegate), - */ YARVINSN_opt_case_dispatch => Some(gen_opt_case_dispatch), YARVINSN_branchif => Some(gen_branchif), YARVINSN_branchunless => Some(gen_branchunless), -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/