// Helper to insert argument slots into the stack. // arg_slots must be a multiple of stack_move_unit() and <= 0 void MethodHandles::insert_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, int arg_mask, Register rax_argslot, Register rbx_temp, Register rdx_temp, Register temp3_reg) { assert(temp3_reg == noreg, "temp3 not required"); assert_different_registers(rax_argslot, rbx_temp, rdx_temp, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); #ifdef ASSERT verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); __ jccb(Assembler::greater, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots <= 0 and clear low bits"); __ bind(L_ok); } else { assert(arg_slots.as_constant() <= 0, ""); assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); } #endif //ASSERT #ifdef _LP64 if (arg_slots.is_register()) { // clean high bits of stack motion register (was loaded as an int) __ movslq(arg_slots.as_register(), arg_slots.as_register()); } #endif // Make space on the stack for the inserted argument(s). // Then pull down everything shallower than rax_argslot. // The stacked return address gets pulled down with everything else. // That is, copy [rsp, argslot) downward by -size words. In pseudo-code: // rsp -= size; // for (rdx = rsp + size; rdx < argslot; rdx++) // rdx[-size] = rdx[0] // argslot -= size; BLOCK_COMMENT("insert_arg_slots {"); __ mov(rdx_temp, rsp); // source pointer for copy __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); { Label loop; __ BIND(loop); // pull one word down each time through the loop __ movptr(rbx_temp, Address(rdx_temp, 0)); __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, wordSize); __ cmpptr(rdx_temp, rax_argslot); __ jccb(Assembler::less, loop); } // Now move the argslot down, to point to the opened-up space. __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); BLOCK_COMMENT("} insert_arg_slots"); }
inline void MacroAssembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) { if (s2.is_register()) sub(s1, s2.as_register(), d); else { sub(s1, s2.as_constant() + offset, d); offset = 0; } if (offset != 0) sub(d, offset, d); }
inline void MacroAssembler::stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, RegisterOrConstant s2) { if (s2.is_register()) stf(w, d, s1, s2.as_register()); else stf(w, d, s1, s2.as_constant()); }
inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, Register s1, RegisterOrConstant s2, FloatRegister d) { if (s2.is_register()) ldf(w, s1, s2.as_register(), d); else ldf(w, s1, s2.as_constant(), d); }
inline void MacroAssembler::andn(Register s1, RegisterOrConstant s2, Register d) { if (s2.is_register()) andn(s1, s2.as_register(), d); else andn(s1, s2.as_constant(), d); }
inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); else sll_ptr(s1, s2.as_constant(), d); }
// Helper to remove argument slots from the stack. // arg_slots must be a multiple of stack_move_unit() and >= 0 void MethodHandles::remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, Register rax_argslot, Register rbx_temp, Register rdx_temp, Register temp3_reg) { assert(temp3_reg == noreg, "temp3 not required"); assert_different_registers(rax_argslot, rbx_temp, rdx_temp, (!arg_slots.is_register() ? rsp : arg_slots.as_register())); #ifdef ASSERT // Verify that [argslot..argslot+size) lies within (rsp, rbp). __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); verify_argslot(_masm, rbx_temp, "deleted argument(s) must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); __ jccb(Assembler::less, L_bad); __ testl(arg_slots.as_register(), -stack_move_unit() - 1); __ jccb(Assembler::zero, L_ok); __ bind(L_bad); __ stop("assert arg_slots >= 0 and clear low bits"); __ bind(L_ok); } else { assert(arg_slots.as_constant() >= 0, ""); assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); } #endif //ASSERT #ifdef _LP64 if (false) { // not needed, since register is positive // clean high bits of stack motion register (was loaded as an int) if (arg_slots.is_register()) __ movslq(arg_slots.as_register(), arg_slots.as_register()); } #endif BLOCK_COMMENT("remove_arg_slots {"); // Pull up everything shallower than rax_argslot. // Then remove the excess space on the stack. // The stacked return address gets pulled up with everything else. // That is, copy [rsp, argslot) upward by size words. In pseudo-code: // for (rdx = argslot-1; rdx >= rsp; --rdx) // rdx[size] = rdx[0] // argslot += size; // rsp += size; __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy { Label loop; __ BIND(loop); // pull one word up each time through the loop __ movptr(rbx_temp, Address(rdx_temp, 0)); __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); __ addptr(rdx_temp, -wordSize); __ cmpptr(rdx_temp, rsp); __ jccb(Assembler::greaterEqual, loop); } // Now move the argslot up, to point to the just-copied block. __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); // And adjust the argslot address to point at the deletion point. __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); BLOCK_COMMENT("} remove_arg_slots"); }
// Helper to remove argument slots from the stack. // arg_slots must be a multiple of stack_move_unit() and >= 0 void MethodHandles::remove_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, Register argslot_reg, Register temp_reg, Register temp2_reg, Register temp3_reg) { assert(temp3_reg != noreg, "temp3 required"); assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg, (!arg_slots.is_register() ? Gargs : arg_slots.as_register())); RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg); #ifdef ASSERT // Verify that [argslot..argslot+size) lies within (Gargs, FP). __ add(argslot_reg, offset, temp2_reg); verify_argslot(_masm, temp2_reg, temp_reg, "deleted argument(s) must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD); __ br(Assembler::less, false, Assembler::pn, L_bad); __ delayed()->nop(); __ btst(-stack_move_unit() - 1, arg_slots.as_register()); __ br(Assembler::zero, false, Assembler::pt, L_ok); __ delayed()->nop(); __ bind(L_bad); __ stop("assert arg_slots >= 0 and clear low bits"); __ bind(L_ok); } else { assert(arg_slots.as_constant() >= 0, ""); assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); } #endif // ASSERT // Pull up everything shallower than argslot. // Then remove the excess space on the stack. // The stacked return address gets pulled up with everything else. // That is, copy [sp, argslot) upward by size words. In pseudo-code: // for (temp = argslot-1; temp >= sp; --temp) // temp[size] = temp[0] // argslot += size; // sp += size; __ sub(argslot_reg, wordSize, temp_reg); // source pointer for copy { Label loop; __ bind(loop); // pull one word up each time through the loop __ ld_ptr(Address(temp_reg, 0), temp2_reg); __ st_ptr(temp2_reg, Address(temp_reg, offset)); __ sub(temp_reg, wordSize, temp_reg); __ cmp(temp_reg, Gargs); __ brx(Assembler::greaterEqual, false, Assembler::pt, loop); __ delayed()->nop(); // FILLME } // Now move the argslot up, to point to the just-copied block. __ add(Gargs, offset, Gargs); // And adjust the argslot address to point at the deletion point. __ add(argslot_reg, offset, argslot_reg); // Keep the stack pointer 2*wordSize aligned. const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1); RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg); __ add(SP, masked_offset, SP); }
// Helper to insert argument slots into the stack. // arg_slots must be a multiple of stack_move_unit() and <= 0 void MethodHandles::insert_arg_slots(MacroAssembler* _masm, RegisterOrConstant arg_slots, int arg_mask, Register argslot_reg, Register temp_reg, Register temp2_reg, Register temp3_reg) { assert(temp3_reg != noreg, "temp3 required"); assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg, (!arg_slots.is_register() ? Gargs : arg_slots.as_register())); #ifdef ASSERT verify_argslot(_masm, argslot_reg, temp_reg, "insertion point must fall within current frame"); if (arg_slots.is_register()) { Label L_ok, L_bad; __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD); __ br(Assembler::greater, false, Assembler::pn, L_bad); __ delayed()->nop(); __ btst(-stack_move_unit() - 1, arg_slots.as_register()); __ br(Assembler::zero, false, Assembler::pt, L_ok); __ delayed()->nop(); __ bind(L_bad); __ stop("assert arg_slots <= 0 and clear low bits"); __ bind(L_ok); } else { assert(arg_slots.as_constant() <= 0, ""); assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); } #endif // ASSERT #ifdef _LP64 if (arg_slots.is_register()) { // Was arg_slots register loaded as signed int? Label L_ok; __ sll(arg_slots.as_register(), BitsPerInt, temp_reg); __ sra(temp_reg, BitsPerInt, temp_reg); __ cmp(arg_slots.as_register(), temp_reg); __ br(Assembler::equal, false, Assembler::pt, L_ok); __ delayed()->nop(); __ stop("arg_slots register not loaded as signed int"); __ bind(L_ok); } #endif // Make space on the stack for the inserted argument(s). // Then pull down everything shallower than argslot_reg. // The stacked return address gets pulled down with everything else. // That is, copy [sp, argslot) downward by -size words. In pseudo-code: // sp -= size; // for (temp = sp + size; temp < argslot; temp++) // temp[-size] = temp[0] // argslot -= size; RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg); // Keep the stack pointer 2*wordSize aligned. const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1); RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg); __ add(SP, masked_offset, SP); __ mov(Gargs, temp_reg); // source pointer for copy __ add(Gargs, offset, Gargs); { Label loop; __ bind(loop); // pull one word down each time through the loop __ ld_ptr(Address(temp_reg, 0), temp2_reg); __ st_ptr(temp2_reg, Address(temp_reg, offset)); __ add(temp_reg, wordSize, temp_reg); __ cmp(temp_reg, argslot_reg); __ brx(Assembler::less, false, Assembler::pt, loop); __ delayed()->nop(); // FILLME } // Now move the argslot down, to point to the opened-up space. __ add(argslot_reg, offset, argslot_reg); }