< prev index next >

src/cpu/x86/vm/sharedRuntime_x86_64.cpp

Print this page

        

*** 26,35 **** --- 26,36 ---- #ifndef _WINDOWS #include "alloca.h" #endif #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" + #include "classfile/symbolTable.hpp" #include "code/debugInfoRec.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "interpreter/interpreter.hpp" #include "oops/compiledICHolder.hpp"
*** 593,603 **** BasicType bt, BasicType prev_bt, size_t size_in_bytes, const VMRegPair& reg_pair, const Address& to, ! int extraspace) { assert(bt != T_VALUETYPE || !ValueTypePassFieldsAsArgs, "no value type here"); if (bt == T_VOID) { assert(prev_bt == T_LONG || prev_bt == T_DOUBLE, "missing half"); return; } --- 594,605 ---- BasicType bt, BasicType prev_bt, size_t size_in_bytes, const VMRegPair& reg_pair, const Address& to, ! int extraspace, ! bool is_oop) { assert(bt != T_VALUETYPE || !ValueTypePassFieldsAsArgs, "no value type here"); if (bt == T_VOID) { assert(prev_bt == T_LONG || prev_bt == T_DOUBLE, "missing half"); return; }
*** 621,636 **** assert(r_2->is_valid() == wide, "invalid size"); if (!r_1->is_valid()) { assert(!r_2->is_valid(), "must be invalid"); return; } ! if (r_1->is_stack()) { int ld_off = r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace; ! __ 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()) { ! __ store_sized_value(to, r_1->as_Register(), size_in_bytes); } else { if (wide) { __ movdbl(to, r_1->as_XMMRegister()); } else { __ movflt(to, r_1->as_XMMRegister()); --- 623,647 ---- assert(r_2->is_valid() == wide, "invalid size"); if (!r_1->is_valid()) { assert(!r_2->is_valid(), "must be invalid"); return; } ! ! if (!r_1->is_XMMRegister()) { ! Register val = rax; ! assert_different_registers(to.base(), val); ! if(r_1->is_stack()) { int ld_off = r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace; ! __ load_sized_value(val, Address(rsp, ld_off), size_in_bytes, /* is_signed */ false); ! } else { ! val = r_1->as_Register(); ! } ! if (is_oop) { ! __ store_heap_oop(to, val); ! } else { ! __ store_sized_value(to, val, size_in_bytes); ! } } else { if (wide) { __ movdbl(to, r_1->as_XMMRegister()); } else { __ movflt(to, r_1->as_XMMRegister());
*** 653,668 **** // compiled target. If there is one, we need to patch the caller's call. patch_callers_callsite(masm); __ bind(skip_fixup); if (ValueTypePassFieldsAsArgs) { ! // Is there a value type arguments? ! int i = 0; ! for (; i < sig_extended.length() && sig_extended.at(i)._bt != T_VALUETYPE; i++); ! ! if (i < sig_extended.length()) { // There is at least a value type argument: we're coming from // compiled code so we have no buffers to back the value // types. Allocate the buffers here with a runtime call. oop_maps = new OopMapSet(); OopMap* map = NULL; --- 664,680 ---- // compiled target. If there is one, we need to patch the caller's call. patch_callers_callsite(masm); __ bind(skip_fixup); + bool has_value_argument = false; if (ValueTypePassFieldsAsArgs) { ! // Is there a value type argument? ! for (int i = 0; i < sig_extended.length() && !has_value_argument; i++) { ! has_value_argument = (sig_extended.at(i)._bt == T_VALUETYPE); ! } ! if (has_value_argument) { // There is at least a value type argument: we're coming from // compiled code so we have no buffers to back the value // types. Allocate the buffers here with a runtime call. oop_maps = new OopMapSet(); OopMap* map = NULL;
*** 692,710 **** __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); __ bind(no_exception); // We get an array of objects from the runtime call - int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(T_OBJECT); __ get_vm_result(r13, r15_thread); __ get_vm_result_2(rbx, r15_thread); // TODO: required to keep the callee Method live? ! __ addptr(r13, offset_in_bytes); ! __ mov(r10, r13); } } - // Since all args are passed on the stack, total_args_passed * // Interpreter::stackElementSize is the space we need. Plus 1 because // we also account for the return address location since // we store it first rather than hold it in rax across all the shuffling int total_args_passed = compute_total_args_passed_int(sig_extended); --- 704,719 ---- __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); __ bind(no_exception); // We get an array of objects from the runtime call __ get_vm_result(r13, r15_thread); __ get_vm_result_2(rbx, r15_thread); // TODO: required to keep the callee Method live? ! __ mov(r10, r13); // Cannot use r10 above because it's trashed by movptr() } } // Since all args are passed on the stack, total_args_passed * // Interpreter::stackElementSize is the space we need. Plus 1 because // we also account for the return address location since // we store it first rather than hold it in rax across all the shuffling int total_args_passed = compute_total_args_passed_int(sig_extended);
*** 734,743 **** --- 743,753 ---- // T_VALUETYPE/T_VOID. next_vt_arg is the next value type argument: // used to get the buffer for that argument from the pool of buffers // we allocated above and want to pass to the // interpreter. next_arg_int is the next argument from the // interpreter point of view (value types are passed by reference). + bool has_oop_field = false; for (int next_arg_comp = 0, ignored = 0, next_vt_arg = 0, next_arg_int = 0; next_arg_comp < sig_extended.length(); next_arg_comp++) { assert(ignored <= next_arg_comp, "shouldn't skip over more slot than there are arguments"); assert(next_arg_int < total_args_passed, "more arguments for the interpreter than expected?"); BasicType bt = sig_extended.at(next_arg_comp)._bt;
*** 746,756 **** int next_off = st_off - Interpreter::stackElementSize; 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, ! size_in_bytes, reg_pair, Address(rsp, offset), extraspace); next_arg_int++; #ifdef ASSERT if (bt == T_LONG || bt == T_DOUBLE) { // Overwrite the unused slot with known junk __ mov64(rax, CONST64(0xdeadffffdeadaaaa)); --- 756,766 ---- int next_off = st_off - Interpreter::stackElementSize; 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, ! size_in_bytes, reg_pair, Address(rsp, offset), extraspace, false); next_arg_int++; #ifdef ASSERT if (bt == T_LONG || bt == T_DOUBLE) { // Overwrite the unused slot with known junk __ mov64(rax, CONST64(0xdeadffffdeadaaaa));
*** 758,768 **** } #endif /* ASSERT */ } else { ignored++; // get the buffer from the just allocated pool of buffers ! __ load_heap_oop(r11, Address(r10, next_vt_arg * type2aelembytes(T_VALUETYPE))); next_vt_arg++; next_arg_int++; int vt = 1; // write fields we get from compiled code in registers/stack // 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 --- 768,779 ---- } #endif /* ASSERT */ } else { ignored++; // get the buffer from the just allocated pool of buffers ! int index = arrayOopDesc::base_offset_in_bytes(T_OBJECT) + next_vt_arg * type2aelembytes(T_VALUETYPE); ! __ load_heap_oop(r11, Address(r10, index)); next_vt_arg++; next_arg_int++; int vt = 1; // write fields we get from compiled code in registers/stack // 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
*** 783,801 **** ignored++; } 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, ! size_in_bytes, regs[next_arg_comp-ignored], Address(r11, off), extraspace); } } while (vt != 0); // pass the buffer to the interpreter __ movptr(Address(rsp, st_off), r11); } } // Schedule the branch target address early. __ movptr(rcx, Address(rbx, in_bytes(Method::interpreter_entry_offset()))); __ jmp(rcx); } --- 794,832 ---- ignored++; } 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; + bool is_oop = (bt == T_OBJECT || bt == T_ARRAY); + has_oop_field = has_oop_field || is_oop; gen_c2i_adapter_helper(masm, bt, next_arg_comp > 0 ? sig_extended.at(next_arg_comp-1)._bt : T_ILLEGAL, ! size_in_bytes, regs[next_arg_comp-ignored], Address(r11, off), extraspace, is_oop); } } while (vt != 0); // pass the buffer to the interpreter __ movptr(Address(rsp, st_off), r11); } } + // If a value type was allocated and initialized, apply post barrier to all oop fields + if (has_value_argument && has_oop_field) { + __ push_CPU_state(); + + // Allocate argument register save area + if (frame::arg_reg_save_area_bytes != 0) { + __ subptr(rsp, frame::arg_reg_save_area_bytes); + } + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::apply_post_barriers), r15_thread, r10, rbx); + // De-allocate argument register save area + if (frame::arg_reg_save_area_bytes != 0) { + __ addptr(rsp, frame::arg_reg_save_area_bytes); + } + + __ pop_CPU_state(); + __ get_vm_result_2(rbx, r15_thread); // TODO: required to keep the callee Method live? + } + // Schedule the branch target address early. __ movptr(rcx, Address(rbx, in_bytes(Method::interpreter_entry_offset()))); __ jmp(rcx); }
*** 815,825 **** 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"); if (bt == T_VOID) { // Longs and doubles are passed in native word order, but misaligned // in the 32-bit build. assert(prev_bt == T_LONG || prev_bt == T_DOUBLE, "missing half"); --- 846,857 ---- 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, ! bool is_oop) { assert(bt != T_VALUETYPE || !ValueTypePassFieldsAsArgs, "no value type here"); if (bt == T_VOID) { // Longs and doubles are passed in native word order, but misaligned // in the 32-bit build. assert(prev_bt == T_LONG || prev_bt == T_DOUBLE, "missing half");
*** 836,857 **** assert(!r_2->is_valid(), "must be invalid"); return; } 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. ! __ 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"); ! __ load_sized_value(r, from, size_in_bytes, is_signed); } else { if (wide) { __ movdbl(r_1->as_XMMRegister(), from); } else { __ movflt(r_1->as_XMMRegister(), from); --- 868,892 ---- assert(!r_2->is_valid(), "must be invalid"); return; } bool is_signed = (bt != T_CHAR) && (bt != T_BOOLEAN); ! if (!r_1->is_XMMRegister()) { // 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. ! Register dst = r_1->is_stack() ? r13 : r_1->as_Register(); ! if (is_oop) { ! __ load_heap_oop(dst, from); ! } else { ! __ load_sized_value(dst, from, size_in_bytes, is_signed); ! } ! 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; ! __ movq(Address(rsp, st_off), dst); ! } } else { if (wide) { __ movdbl(r_1->as_XMMRegister(), from); } else { __ movflt(r_1->as_XMMRegister(), from);
*** 989,999 **** int next_off = ld_off - Interpreter::stackElementSize; 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, ! size_in_bytes, reg_pair, Address(saved_sp, offset)); next_arg_int++; } else { next_arg_int++; ignored++; // get the buffer for that value type --- 1024,1034 ---- int next_off = ld_off - Interpreter::stackElementSize; 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, ! size_in_bytes, reg_pair, Address(saved_sp, offset), false); next_arg_int++; } else { next_arg_int++; ignored++; // get the buffer for that value type
*** 1019,1029 **** ignored++; } 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_i2c_adapter_helper(masm, bt, prev_bt, size_in_bytes, regs[next_arg_comp - ignored], Address(r10, off)); } } while (vt != 0); } } --- 1054,1065 ---- ignored++; } 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; ! bool is_oop = (bt == T_OBJECT || bt == T_ARRAY); ! gen_i2c_adapter_helper(masm, bt, prev_bt, size_in_bytes, regs[next_arg_comp - ignored], Address(r10, off), is_oop); } } while (vt != 0); } }
*** 1097,1107 **** int frame_size_in_words = 0; gen_c2i_adapter(masm, sig_extended, regs, skip_fixup, i2c_entry, oop_maps, frame_complete, frame_size_in_words); __ flush(); new_adapter = AdapterBlob::create(masm->code(), frame_complete, frame_size_in_words, oop_maps); ! return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); } int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, VMRegPair *regs2, --- 1133,1178 ---- int frame_size_in_words = 0; gen_c2i_adapter(masm, sig_extended, regs, skip_fixup, i2c_entry, oop_maps, frame_complete, frame_size_in_words); __ flush(); new_adapter = AdapterBlob::create(masm->code(), frame_complete, frame_size_in_words, oop_maps); ! ! // If value types are passed as fields, save the extended signature as symbol in ! // the AdapterHandlerEntry to be used by nmethod::preserve_callee_argument_oops(). ! Symbol* extended_signature = NULL; ! if (ValueTypePassFieldsAsArgs) { ! bool has_value_argument = false; ! Thread* THREAD = Thread::current(); ! ResourceMark rm(THREAD); ! int length = sig_extended.length(); ! // TODO is 256 enough? Can we determine the required length? ! char* sig_str = NEW_RESOURCE_ARRAY(char, 256); ! int idx = 0; ! sig_str[idx++] = '('; ! for (int index = 0; index < length; index++ ) { ! BasicType bt = sig_extended.at(index)._bt; ! if (bt == T_VALUETYPE || bt == T_VOID) { ! has_value_argument = true; ! continue; // Ignore wrapper types ! } ! sig_str[idx++] = type2char(bt); ! if (bt == T_OBJECT) { ! sig_str[idx++] = ';'; ! } else if (bt == T_ARRAY) { ! // We don't know the array element type, put void as placeholder ! sig_str[idx++] = 'V'; ! } ! } ! sig_str[idx++] = ')'; ! sig_str[idx++] = '\0'; ! if (has_value_argument) { ! // Extended signature is only required if a value type argument is passed ! extended_signature = SymbolTable::new_permanent_symbol(sig_str, THREAD); ! } ! } ! ! return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, extended_signature); } int SharedRuntime::c_calling_convention(const BasicType *sig_bt, VMRegPair *regs, VMRegPair *regs2,
< prev index next >