< prev index next >

src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp

Print this page

        

*** 350,360 **** case T_BOOLEAN: case T_CHAR: case T_BYTE: case T_SHORT: case T_INT: ! if (int_args < Argument::n_int_register_parameters_j) { regs[i].set1(INT_ArgReg[int_args]->as_VMReg()); int_args ++; } else { // Should we have gurantee here? return -1; --- 350,360 ---- case T_BOOLEAN: case T_CHAR: case T_BYTE: case T_SHORT: case T_INT: ! if (int_args < SharedRuntime::java_return_convention_max_int) { regs[i].set1(INT_ArgReg[int_args]->as_VMReg()); int_args ++; } else { // Should we have gurantee here? return -1;
*** 372,390 **** case T_ARRAY: case T_ADDRESS: // Should T_METADATA be added to java_calling_convention as well ? case T_METADATA: case T_VALUETYPE: ! if (int_args < Argument::n_int_register_parameters_j) { regs[i].set2(INT_ArgReg[int_args]->as_VMReg()); int_args ++; } else { return -1; } break; case T_FLOAT: ! if (fp_args < Argument::n_float_register_parameters_j) { regs[i].set1(FP_ArgReg[fp_args]->as_VMReg()); fp_args ++; } else { return -1; } --- 372,390 ---- case T_ARRAY: case T_ADDRESS: // Should T_METADATA be added to java_calling_convention as well ? case T_METADATA: case T_VALUETYPE: ! if (int_args < SharedRuntime::java_return_convention_max_int) { regs[i].set2(INT_ArgReg[int_args]->as_VMReg()); int_args ++; } else { return -1; } break; case T_FLOAT: ! if (fp_args < SharedRuntime::java_return_convention_max_float) { regs[i].set1(FP_ArgReg[fp_args]->as_VMReg()); fp_args ++; } else { return -1; }
*** 441,457 **** --- 441,495 ---- // the value type. This utility function computes the number of // arguments for the call if value types are passed by reference (the // calling convention the interpreter expects). static int compute_total_args_passed_int(const GrowableArray<SigEntry>* sig_extended) { int total_args_passed = 0; + if (ValueTypePassFieldsAsArgs) { + for (int i = 0; i < sig_extended->length(); i++) { + BasicType bt = sig_extended->at(i)._bt; + if (SigEntry::is_reserved_entry(sig_extended, i)) { + // Ignore reserved entry + } else if (bt == T_VALUETYPE) { + // In sig_extended, a value type argument starts with: + // T_VALUETYPE, followed by the types of the fields of the + // value type and T_VOID to mark the end of the value + // type. Value types are flattened so, for instance, in the + // case of a value type with an int field and a value type + // field that itself has 2 fields, an int and a long: + // T_VALUETYPE T_INT T_VALUETYPE T_INT T_LONG T_VOID (second + // slot for the T_LONG) T_VOID (inner T_VALUETYPE) T_VOID + // (outer T_VALUETYPE) + total_args_passed++; + int vt = 1; + do { + i++; + BasicType bt = sig_extended->at(i)._bt; + BasicType prev_bt = sig_extended->at(i-1)._bt; + if (bt == T_VALUETYPE) { + vt++; + } else if (bt == T_VOID && + prev_bt != T_LONG && + prev_bt != T_DOUBLE) { + vt--; + } + } while (vt != 0); + } else { + total_args_passed++; + } + } + } else { total_args_passed = sig_extended->length(); + } + return total_args_passed; } static void gen_c2i_adapter_helper(MacroAssembler* masm, BasicType bt, const VMRegPair& reg_pair, int extraspace, const Address& to) { + assert(bt != T_VALUETYPE || !ValueTypePassFieldsAsArgs, "no value type here"); + // Say 4 args: // i st_off // 0 32 T_LONG // 1 24 T_VOID // 2 16 T_OBJECT
*** 473,485 **** return; } if (r_1->is_stack()) { // memory to memory use rscratch1 ! // DMS CHECK: words_pushed is always 0 and can be removed? ! // int ld_off = (r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace + words_pushed * wordSize); ! int ld_off = (r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace); if (!r_2->is_valid()) { // sign extend?? __ ldrw(rscratch1, Address(sp, ld_off)); __ str(rscratch1, to); --- 511,522 ---- return; } if (r_1->is_stack()) { // memory to memory use rscratch1 ! // words_pushed is always 0 so we don't use it. ! int ld_off = (r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace /* + word_pushed * wordSize */); if (!r_2->is_valid()) { // sign extend?? __ ldrw(rscratch1, Address(sp, ld_off)); __ str(rscratch1, to);
*** 519,528 **** --- 556,610 ---- 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. + OopMap* map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + + frame_complete = __ offset(); + address the_pc = __ pc(); + + __ set_last_Java_frame(noreg, noreg, the_pc, rscratch1); + + __ mov(c_rarg0, rthread); + __ mov(c_rarg1, r1); + __ mov(c_rarg2, (int64_t)alloc_value_receiver); + + __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::allocate_value_types))); + __ blrt(rscratch1, 3, 0, 1); + + oop_maps->add_gc_map((int)(__ pc() - start), map); + __ reset_last_Java_frame(false); + + RegisterSaver::restore_live_registers(masm); + + Label no_exception; + __ ldr(r0, Address(rthread, Thread::pending_exception_offset())); + __ cbz(r0, no_exception); + + __ str(zr, Address(rthread, JavaThread::vm_result_offset())); + __ ldr(r0, Address(rthread, Thread::pending_exception_offset())); + __ b(RuntimeAddress(StubRoutines::forward_exception_entry())); + + __ bind(no_exception); + + // We get an array of objects from the runtime call + __ get_vm_result(r10, rthread); + __ get_vm_result_2(r1, rthread); // TODO: required to keep the callee Method live? + } + } + int words_pushed = 0; // Since all args are passed on the stack, total_args_passed * // Interpreter::stackElementSize is the space we need.
*** 545,554 **** --- 627,638 ---- for (int next_arg_comp = 0; next_arg_comp < total_args_passed; next_arg_comp++) { BasicType bt = sig_extended->at(next_arg_comp)._bt; // offset to start parameters int st_off = (total_args_passed - next_arg_int - 1) * Interpreter::stackElementSize; + if (!ValueTypePassFieldsAsArgs || bt != T_VALUETYPE) { + if (SigEntry::is_reserved_entry(sig_extended, next_arg_comp)) { continue; // Ignore reserved entry } if (bt == T_VOID) {
*** 560,569 **** --- 644,693 ---- int next_off = st_off - Interpreter::stackElementSize; int offset = (bt == T_LONG || bt == T_DOUBLE) ? next_off : st_off; gen_c2i_adapter_helper(masm, bt, regs[next_arg_comp], extraspace, Address(sp, offset)); next_arg_int ++; + } 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(rscratch1, 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 + // type delimiter for this 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 { + next_arg_comp++; + BasicType bt = sig_extended->at(next_arg_comp)._bt; + BasicType prev_bt = sig_extended->at(next_arg_comp - 1)._bt; + if (bt == T_VALUETYPE) { + vt++; + ignored++; + } else if (bt == T_VOID && prev_bt != T_LONG && prev_bt != T_DOUBLE) { + vt--; + ignored++; + } else if (SigEntry::is_reserved_entry(sig_extended, next_arg_comp)) { + // Ignore reserved entry + } else { + int off = sig_extended->at(next_arg_comp)._offset; + assert(off > 0, "offset in object should be positive"); + + bool is_oop = (bt == T_OBJECT || bt == T_ARRAY); + has_oop_field = has_oop_field || is_oop; + + gen_c2i_adapter_helper(masm, bt, regs[next_arg_comp - ignored], extraspace, Address(r11, off)); + } + } while (vt != 0); + // pass the buffer to the interpreter + __ str(rscratch1, Address(sp, st_off)); + } + } // If a value type was allocated and initialized, apply post barrier to all oop fields if (has_value_argument && has_oop_field) { __ push(r13); // save senderSP
< prev index next >