--- old/src/cpu/x86/vm/sharedRuntime_x86_64.cpp 2017-03-23 15:38:40.342380443 +0100 +++ new/src/cpu/x86/vm/sharedRuntime_x86_64.cpp 2017-03-23 15:38:40.258380441 +0100 @@ -589,9 +589,10 @@ } -static void gen_c2i_adapter_helper(MacroAssembler *masm, +static void gen_c2i_adapter_helper(MacroAssembler* masm, BasicType bt, BasicType prev_bt, + size_t size_in_bytes, const VMRegPair& reg_pair, const Address& to, int extraspace) { @@ -614,41 +615,25 @@ // leaves one slot empty and only stores to a single slot. In this case the // slot that is occupied is the T_VOID slot. See I said it was confusing. + bool wide = (size_in_bytes == wordSize); VMReg r_1 = reg_pair.first(); VMReg r_2 = reg_pair.second(); + assert(r_2->is_valid() == wide, "invalid size"); if (!r_1->is_valid()) { - assert(!r_2->is_valid(), ""); + assert(!r_2->is_valid(), "must be invalid"); return; } if (r_1->is_stack()) { - // memory to memory use rax int ld_off = r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace; - if (!r_2->is_valid()) { - // sign extend?? - __ movl(rax, Address(rsp, ld_off)); - __ movl(to, rax); - - } else { - - __ movq(rax, Address(rsp, ld_off)); - __ movq(to, rax); - } + __ load_sized_value(rax, Address(rsp, ld_off), size_in_bytes, /* is_signed */ false); + __ store_sized_value(to, rax, size_in_bytes); } else if (r_1->is_Register()) { - Register r = r_1->as_Register(); - if (!r_2->is_valid()) { - // must be only an int (or less ) so move only 32bits to slot - // why not sign extend?? - __ movl(to, r); - } else { - __ movq(to, r); - } + __ store_sized_value(to, r_1->as_Register(), size_in_bytes); } else { - assert(r_1->is_XMMRegister(), ""); - if (!r_2->is_valid()) { - // only a float use just part of the slot - __ movflt(to, r_1->as_XMMRegister()); - } else { + if (wide) { __ movdbl(to, r_1->as_XMMRegister()); + } else { + __ movflt(to, r_1->as_XMMRegister()); } } } @@ -759,12 +744,14 @@ int st_off = (total_args_passed - next_arg_int) * Interpreter::stackElementSize; if (!ValueTypePassFieldsAsArgs || bt != T_VALUETYPE) { int next_off = st_off - Interpreter::stackElementSize; - const int offset = (bt==T_LONG||bt==T_DOUBLE) ? next_off : st_off; + const int offset = (bt == T_LONG || bt == T_DOUBLE) ? next_off : st_off; + const VMRegPair reg_pair = regs[next_arg_comp-ignored]; + size_t size_in_bytes = reg_pair.second()->is_valid() ? 8 : 4; gen_c2i_adapter_helper(masm, bt, next_arg_comp > 0 ? sig_extended.at(next_arg_comp-1)._bt : T_ILLEGAL, - regs[next_arg_comp-ignored], Address(rsp, offset), extraspace); + size_in_bytes, reg_pair, Address(rsp, offset), extraspace); next_arg_int++; #ifdef ASSERT - if (bt==T_LONG || bt==T_DOUBLE) { + if (bt == T_LONG || bt == T_DOUBLE) { // Overwrite the unused slot with known junk __ mov64(rax, CONST64(0xdeadffffdeadaaaa)); __ movptr(Address(rsp, st_off), rax); @@ -780,7 +767,7 @@ // slots to the buffer: we know we are done with that value type // argument when we hit the T_VOID that acts as an end of value // type delimiter for this value type. Value types are flattened - // so we might encounter a embedded value types. Each entry in + // so we might encounter embedded value types. Each entry in // sig_extended contains a field offset in the buffer. do { next_arg_comp++; @@ -797,8 +784,9 @@ } else { int off = sig_extended.at(next_arg_comp)._offset; assert(off > 0, "offset in object should be positive"); + size_t size_in_bytes = is_java_primitive(bt) ? type2aelembytes(bt) : wordSize; gen_c2i_adapter_helper(masm, bt, next_arg_comp > 0 ? sig_extended.at(next_arg_comp-1)._bt : T_ILLEGAL, - regs[next_arg_comp-ignored], Address(r11, off), extraspace); + size_in_bytes, regs[next_arg_comp-ignored], Address(r11, off), extraspace); } } while (vt != 0); // pass the buffer to the interpreter @@ -824,9 +812,10 @@ __ bind(L_fail); } -static void gen_i2c_adapter_helper(MacroAssembler *masm, +static void gen_i2c_adapter_helper(MacroAssembler* masm, BasicType bt, BasicType prev_bt, + size_t size_in_bytes, const VMRegPair& reg_pair, const Address& from) { assert(bt != T_VALUETYPE || !ValueTypePassFieldsAsArgs, "no value type here"); @@ -836,64 +825,36 @@ assert(prev_bt == T_LONG || prev_bt == T_DOUBLE, "missing half"); return; } - // Pick up 0, 1 or 2 words from SP+offset. - assert(!reg_pair.second()->is_valid() || reg_pair.first()->next() == reg_pair.second(), "scrambled load targets?"); - // - // - // + + bool wide = (size_in_bytes == wordSize); VMReg r_1 = reg_pair.first(); VMReg r_2 = reg_pair.second(); + assert(r_2->is_valid() == wide, "invalid size"); if (!r_1->is_valid()) { - assert(!r_2->is_valid(), ""); + assert(!r_2->is_valid(), "must be invalid"); return; } - if (r_1->is_stack()) { - // Convert stack slot to an SP offset (+ wordSize to account for return address ) - int st_off = reg_pair.first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize; + bool is_signed = (bt != T_CHAR) && (bt != T_BOOLEAN); + if (r_1->is_stack()) { + // Convert stack slot to an SP offset (+ wordSize to account for return address) + int st_off = reg_pair.first()->reg2stack() * VMRegImpl::stack_slot_size + wordSize; // We can use r13 as a temp here because compiled code doesn't need r13 as an input // and if we end up going thru a c2i because of a miss a reasonable value of r13 // will be generated. - if (!r_2->is_valid()) { - // sign extend??? - __ movl(r13, from); - __ movptr(Address(rsp, st_off), r13); - } else { - // - // We are using two optoregs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE - // the interpreter allocates two slots but only uses one for thr T_LONG or T_DOUBLE case - // So we must adjust where to pick up the data to match the interpreter. - // - // Interpreter local[n] == MSW, local[n+1] == LSW however locals - // are accessed as negative so LSW is at LOW address - - // ld_off is MSW so get LSW - __ movq(r13, from); - // st_off is LSW (i.e. reg.first()) - __ movq(Address(rsp, st_off), r13); - } - } else if (r_1->is_Register()) { // Register argument + __ load_sized_value(r13, from, size_in_bytes, is_signed); + __ movq(Address(rsp, st_off), r13); + } else if (r_1->is_Register()) { Register r = r_1->as_Register(); assert(r != rax, "must be different"); - if (r_2->is_valid()) { - // - // We are using two VMRegs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE - // the interpreter allocates two slots but only uses one for thr T_LONG or T_DOUBLE case - // So we must adjust where to pick up the data to match the interpreter. - - // this can be a misaligned move - __ movq(r, from); - } else { - // sign extend and use a full word? - __ movl(r, from); - } + __ load_sized_value(r, from, size_in_bytes, is_signed); } else { - if (!r_2->is_valid()) { - __ movflt(r_1->as_XMMRegister(), from); - } else { + if (wide) { __ movdbl(r_1->as_XMMRegister(), from); + } else { + __ movflt(r_1->as_XMMRegister(), from); } } } @@ -1026,9 +987,11 @@ // Load in argument order going down. // Point to interpreter value (vs. tag) int next_off = ld_off - Interpreter::stackElementSize; - const int offset = (bt==T_LONG||bt==T_DOUBLE) ? next_off : ld_off; + int offset = (bt == T_LONG || bt == T_DOUBLE) ? next_off : ld_off; + const VMRegPair reg_pair = regs[next_arg_comp-ignored]; + size_t size_in_bytes = reg_pair.second()->is_valid() ? 8 : 4; gen_i2c_adapter_helper(masm, bt, next_arg_comp > 0 ? sig_extended.at(next_arg_comp-1)._bt : T_ILLEGAL, - regs[next_arg_comp-ignored], Address(saved_sp, offset)); + size_in_bytes, reg_pair, Address(saved_sp, offset)); next_arg_int++; } else { next_arg_int++; @@ -1039,7 +1002,7 @@ // load fields to registers/stack slots from the buffer: we know // we are done with that value type argument when we hit the // T_VOID that acts as an end of value type delimiter for this - // value type. Value types are flattened so we might encounter a + // value type. Value types are flattened so we might encounter // embedded value types. Each entry in sig_extended contains a // field offset in the buffer. do { @@ -1057,7 +1020,8 @@ } else { int off = sig_extended.at(next_arg_comp)._offset; assert(off > 0, "offset in object should be positive"); - gen_i2c_adapter_helper(masm, bt, prev_bt, regs[next_arg_comp - ignored], Address(r10, off)); + size_t size_in_bytes = is_java_primitive(bt) ? type2aelembytes(bt) : wordSize; + gen_i2c_adapter_helper(masm, bt, prev_bt, size_in_bytes, regs[next_arg_comp - ignored], Address(r10, off)); } } while (vt != 0); }