author | twisti |
Wed, 10 Feb 2016 11:23:17 -1000 | |
changeset 36060 | de5c192c2eac |
parent 36059 | 5ae62468859f |
child 36061 | baa556050d22 |
--- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp Wed Feb 10 11:23:17 2016 -1000 @@ -30,39 +30,151 @@ #include "vmreg_aarch64.inline.hpp" jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) { - Unimplemented(); - return 0; + if (inst->is_call() || inst->is_jump() || inst->is_blr()) { + return pc_offset + NativeCall::instruction_size; + } else if (inst->is_general_jump()) { + return pc_offset + NativeGeneralJump::instruction_size; + } else { + JVMCI_ERROR_0("unsupported type of instruction for call site"); + } } void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { - Unimplemented(); + address pc = _instructions->start() + pc_offset; + Handle obj = HotSpotObjectConstantImpl::object(constant); + jobject value = JNIHandles::make_local(obj()); + if (HotSpotObjectConstantImpl::compressed(constant)) { + int oop_index = _oop_recorder->find_index(value); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + _instructions->relocate(pc, rspec, 1); + Unimplemented(); + } else { + NativeMovConstReg* move = nativeMovConstReg_at(pc); + move->set_data((intptr_t) value); + int oop_index = _oop_recorder->find_index(value); + RelocationHolder rspec = oop_Relocation::spec(oop_index); + _instructions->relocate(pc, rspec); + } } void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) { - Unimplemented(); + address pc = _instructions->start() + pc_offset; + if (HotSpotMetaspaceConstantImpl::compressed(constant)) { + narrowKlass narrowOop = record_narrow_metadata_reference(constant, CHECK); + TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop); + Unimplemented(); + } else { + NativeMovConstReg* move = nativeMovConstReg_at(pc); + Metadata* reference = record_metadata_reference(constant, CHECK); + move->set_data((intptr_t) reference); + TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference)); + } } void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) { - Unimplemented(); + address pc = _instructions->start() + pc_offset; + NativeInstruction* inst = nativeInstruction_at(pc); + if (inst->is_adr_aligned()) { + address dest = _constants->start() + data_offset; + _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); + TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); + } else { + JVMCI_ERROR("unknown load or move instruction at " PTR_FORMAT, p2i(pc)); + } } void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) { - Unimplemented(); + address pc = (address) inst; + if (inst->is_call()) { + NativeCall* call = nativeCall_at(pc); + call->set_destination((address) foreign_call_destination); + _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); + } else if (inst->is_jump()) { + NativeJump* jump = nativeJump_at(pc); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); + } else if (inst->is_general_jump()) { + NativeGeneralJump* jump = nativeGeneralJump_at(pc); + jump->set_jump_destination((address) foreign_call_destination); + _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); + } else { + JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)); + } + TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); } void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) { - Unimplemented(); +#ifdef ASSERT + Method* method = NULL; + // we need to check, this might also be an unresolved method + if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) { + method = getMethodFromHotSpotMethod(hotspot_method()); + } +#endif + switch (_next_call_type) { + case INLINE_INVOKE: + break; + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); + break; + } + case INVOKESTATIC: { + assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_static_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); + break; + } + case INVOKESPECIAL: { + assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); + NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); + call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); + _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); + break; + } + default: + JVMCI_ERROR("invalid _next_call_type value"); + break; + } } void CodeInstaller::pd_relocate_poll(address pc, jint mark, TRAPS) { - Unimplemented(); + switch (mark) { + case POLL_NEAR: + JVMCI_ERROR("unimplemented"); + break; + case POLL_FAR: + _instructions->relocate(pc, relocInfo::poll_type); + break; + case POLL_RETURN_NEAR: + JVMCI_ERROR("unimplemented"); + break; + case POLL_RETURN_FAR: + _instructions->relocate(pc, relocInfo::poll_return_type); + break; + default: + JVMCI_ERROR("invalid mark value"); + break; + } } // convert JVMCI register indices (as used in oop maps) to HotSpot registers VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg, TRAPS) { - return NULL; + if (jvmci_reg < RegisterImpl::number_of_registers) { + return as_Register(jvmci_reg)->as_VMReg(); + } else { + jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers; + if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) { + return as_FloatRegister(floatRegisterNumber)->as_VMReg(); + } + JVMCI_ERROR_NULL("invalid register number: %d", jvmci_reg); + } } bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) { - return false; + return !hotspotRegister->is_FloatRegister(); }
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.cpp Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.cpp Wed Feb 10 11:23:17 2016 -1000 @@ -136,7 +136,7 @@ MacroAssembler::pd_patch_instruction(instruction_address(), (address)x); ICache::invalidate_range(instruction_address(), instruction_size); } -}; +} void NativeMovConstReg::print() { tty->print_cr(PTR_FORMAT ": mov reg, " INTPTR_FORMAT, @@ -208,6 +208,32 @@ //------------------------------------------------------------------- +address NativeGeneralJump::jump_destination() const { + NativeMovConstReg* move = nativeMovConstReg_at(instruction_address()); + address dest = (address) move->data(); + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about + + // return -1 if jump to self + dest = (dest == (address) this) ? (address) -1 : dest; + return dest; +} + +void NativeGeneralJump::set_jump_destination(address dest) { + NativeMovConstReg* move = nativeMovConstReg_at(instruction_address()); + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about + if (dest == (address) -1) { + dest = instruction_address(); + } + + move->set_data((uintptr_t) dest); +}; + +//------------------------------------------------------------------- + bool NativeInstruction::is_safepoint_poll() { // a safepoint_poll is implemented in two steps as either // @@ -249,6 +275,22 @@ Instruction_aarch64::extract(insn, 4, 0) == 0b11111); } +bool NativeInstruction::is_general_jump() { + if (is_movz()) { + NativeInstruction* inst1 = nativeInstruction_at(addr_at(instruction_size * 1)); + if (inst1->is_movk()) { + NativeInstruction* inst2 = nativeInstruction_at(addr_at(instruction_size * 2)); + if (inst2->is_movk()) { + NativeInstruction* inst3 = nativeInstruction_at(addr_at(instruction_size * 3)); + if (inst3->is_blr()) { + return true; + } + } + } + } + return false; +} + bool NativeInstruction::is_movz() { return Instruction_aarch64::extract(int_at(0), 30, 23) == 0b10100101; }
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp Wed Feb 10 11:23:17 2016 -1000 @@ -54,11 +54,22 @@ friend class Relocation; friend bool is_NativeCallTrampolineStub_at(address); public: - enum { instruction_size = 4 }; + enum { + instruction_size = 4 + }; + + juint encoding() const { + return uint_at(0); + } + + bool is_blr() const { return (encoding() & 0xfffffc1f) == 0xd63f0000; } + bool is_adr_aligned() const { return (encoding() & 0xff000000) == 0x10000000; } // adr Xn, <label>, where label is aligned to 4 bytes (address of instruction). + inline bool is_nop(); inline bool is_illegal(); inline bool is_return(); bool is_jump(); + bool is_general_jump(); inline bool is_jump_or_nop(); inline bool is_cond_jump(); bool is_safepoint_poll(); @@ -341,11 +352,15 @@ // An interface for accessing/manipulating native leal instruction of form: // leal reg, [reg + offset] -class NativeLoadAddress: public NativeMovRegMem { - static const bool has_rex = true; - static const int rex_size = 1; +class NativeLoadAddress: public NativeInstruction { + enum AArch64_specific_constants { + instruction_size = 4, + instruction_offset = 0, + data_offset = 0, + next_instruction_offset = 4 + }; + public: - void verify(); void print (); @@ -398,6 +413,10 @@ data_offset = 0, next_instruction_offset = 4 * 4 }; + + address jump_destination() const; + void set_jump_destination(address dest); + static void insert_unconditional(address code_pos, address entry); static void replace_mt_safe(address instr_addr, address code_buffer); static void verify();
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java Wed Feb 10 11:23:17 2016 -1000 @@ -70,56 +70,64 @@ public static final Register r28 = new Register(28, 28, "r28", CPU); public static final Register r29 = new Register(29, 29, "r29", CPU); public static final Register r30 = new Register(30, 30, "r30", CPU); + + /* + * r31 is not a general purpose register, but represents either the stackpointer or the + * zero/discard register depending on the instruction. So we represent those two uses as two + * different registers. The register numbers are kept in sync with register_aarch64.hpp and have + * to be sequential, hence we also need a general r31 register here, which is never used. + */ public static final Register r31 = new Register(31, 31, "r31", CPU); + public static final Register zr = new Register(32, 31, "zr", CPU); + public static final Register sp = new Register(33, 31, "sp", CPU); public static final Register lr = r30; - public static final Register zr = r31; - public static final Register sp = r31; // @formatter:off public static final Register[] cpuRegisters = { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, - r24, r25, r26, r27, r28, r29, r30, r31 + r24, r25, r26, r27, r28, r29, r30, r31, + zr, sp }; // @formatter:on public static final RegisterCategory SIMD = new RegisterCategory("SIMD"); // Simd registers - public static final Register v0 = new Register(32, 0, "v0", SIMD); - public static final Register v1 = new Register(33, 1, "v1", SIMD); - public static final Register v2 = new Register(34, 2, "v2", SIMD); - public static final Register v3 = new Register(35, 3, "v3", SIMD); - public static final Register v4 = new Register(36, 4, "v4", SIMD); - public static final Register v5 = new Register(37, 5, "v5", SIMD); - public static final Register v6 = new Register(38, 6, "v6", SIMD); - public static final Register v7 = new Register(39, 7, "v7", SIMD); - public static final Register v8 = new Register(40, 8, "v8", SIMD); - public static final Register v9 = new Register(41, 9, "v9", SIMD); - public static final Register v10 = new Register(42, 10, "v10", SIMD); - public static final Register v11 = new Register(43, 11, "v11", SIMD); - public static final Register v12 = new Register(44, 12, "v12", SIMD); - public static final Register v13 = new Register(45, 13, "v13", SIMD); - public static final Register v14 = new Register(46, 14, "v14", SIMD); - public static final Register v15 = new Register(47, 15, "v15", SIMD); - public static final Register v16 = new Register(48, 16, "v16", SIMD); - public static final Register v17 = new Register(49, 17, "v17", SIMD); - public static final Register v18 = new Register(50, 18, "v18", SIMD); - public static final Register v19 = new Register(51, 19, "v19", SIMD); - public static final Register v20 = new Register(52, 20, "v20", SIMD); - public static final Register v21 = new Register(53, 21, "v21", SIMD); - public static final Register v22 = new Register(54, 22, "v22", SIMD); - public static final Register v23 = new Register(55, 23, "v23", SIMD); - public static final Register v24 = new Register(56, 24, "v24", SIMD); - public static final Register v25 = new Register(57, 25, "v25", SIMD); - public static final Register v26 = new Register(58, 26, "v26", SIMD); - public static final Register v27 = new Register(59, 27, "v27", SIMD); - public static final Register v28 = new Register(60, 28, "v28", SIMD); - public static final Register v29 = new Register(61, 29, "v29", SIMD); - public static final Register v30 = new Register(62, 30, "v30", SIMD); - public static final Register v31 = new Register(63, 31, "v31", SIMD); + public static final Register v0 = new Register(34, 0, "v0", SIMD); + public static final Register v1 = new Register(35, 1, "v1", SIMD); + public static final Register v2 = new Register(36, 2, "v2", SIMD); + public static final Register v3 = new Register(37, 3, "v3", SIMD); + public static final Register v4 = new Register(38, 4, "v4", SIMD); + public static final Register v5 = new Register(39, 5, "v5", SIMD); + public static final Register v6 = new Register(40, 6, "v6", SIMD); + public static final Register v7 = new Register(41, 7, "v7", SIMD); + public static final Register v8 = new Register(42, 8, "v8", SIMD); + public static final Register v9 = new Register(43, 9, "v9", SIMD); + public static final Register v10 = new Register(44, 10, "v10", SIMD); + public static final Register v11 = new Register(45, 11, "v11", SIMD); + public static final Register v12 = new Register(46, 12, "v12", SIMD); + public static final Register v13 = new Register(47, 13, "v13", SIMD); + public static final Register v14 = new Register(48, 14, "v14", SIMD); + public static final Register v15 = new Register(49, 15, "v15", SIMD); + public static final Register v16 = new Register(50, 16, "v16", SIMD); + public static final Register v17 = new Register(51, 17, "v17", SIMD); + public static final Register v18 = new Register(52, 18, "v18", SIMD); + public static final Register v19 = new Register(53, 19, "v19", SIMD); + public static final Register v20 = new Register(54, 20, "v20", SIMD); + public static final Register v21 = new Register(55, 21, "v21", SIMD); + public static final Register v22 = new Register(56, 22, "v22", SIMD); + public static final Register v23 = new Register(57, 23, "v23", SIMD); + public static final Register v24 = new Register(58, 24, "v24", SIMD); + public static final Register v25 = new Register(59, 25, "v25", SIMD); + public static final Register v26 = new Register(60, 26, "v26", SIMD); + public static final Register v27 = new Register(61, 27, "v27", SIMD); + public static final Register v28 = new Register(62, 28, "v28", SIMD); + public static final Register v29 = new Register(63, 29, "v29", SIMD); + public static final Register v30 = new Register(64, 30, "v30", SIMD); + public static final Register v31 = new Register(65, 31, "v31", SIMD); // @formatter:off public static final Register[] simdRegisters = { @@ -136,6 +144,7 @@ r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30, r31, + zr, sp, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java Wed Feb 10 11:23:17 2016 -1000 @@ -31,6 +31,7 @@ import static jdk.vm.ci.aarch64.AArch64.r28; import static jdk.vm.ci.aarch64.AArch64.r29; import static jdk.vm.ci.aarch64.AArch64.r3; +import static jdk.vm.ci.aarch64.AArch64.r31; import static jdk.vm.ci.aarch64.AArch64.r4; import static jdk.vm.ci.aarch64.AArch64.r5; import static jdk.vm.ci.aarch64.AArch64.r6; @@ -45,11 +46,13 @@ import static jdk.vm.ci.aarch64.AArch64.v5; import static jdk.vm.ci.aarch64.AArch64.v6; import static jdk.vm.ci.aarch64.AArch64.v7; +import static jdk.vm.ci.aarch64.AArch64.zr; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import jdk.vm.ci.aarch64.AArch64; @@ -130,16 +133,20 @@ public static final Register threadRegister = r28; public static final Register fp = r29; + private static final Register[] reservedRegisters = {threadRegister, fp, lr, r31, zr, sp}; + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { Register[] allRegisters = arch.getAvailableValueRegisters(); - Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 5 : 4)]; + Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)]; + List<Register> reservedRegistersList = Arrays.asList(reservedRegisters); int idx = 0; for (Register reg : allRegisters) { - if (reg.equals(threadRegister) || reg.equals(fp) || reg.equals(lr) || reg.equals(sp)) { - // skip thread register, frame pointer, link register and stack pointer + if (reservedRegistersList.contains(reg)) { + // skip reserved registers continue; } + assert !(reg.equals(threadRegister) || reg.equals(fp) || reg.equals(lr) || reg.equals(r31) || reg.equals(zr) || reg.equals(sp)); if (reserveForHeapBase && reg.equals(heapBaseRegister)) { // skip heap base register continue;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java Wed Feb 10 11:23:17 2016 -1000 @@ -45,6 +45,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import jdk.vm.ci.code.Architecture; @@ -119,14 +120,17 @@ */ private final boolean needsNativeStackHomeSpace; + private static final Register[] reservedRegisters = {rsp, r15}; + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { Register[] allRegisters = arch.getAvailableValueRegisters(); - Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)]; + Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)]; + List<Register> reservedRegistersList = Arrays.asList(reservedRegisters); int idx = 0; for (Register reg : allRegisters) { - if (reg.equals(rsp) || reg.equals(r15)) { - // skip stack pointer and thread register + if (reservedRegistersList.contains(reg)) { + // skip reserved registers continue; } if (reserveForHeapBase && reg.equals(r12)) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Feb 10 16:31:17 2016 +0000 +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java Wed Feb 10 11:23:17 2016 -1000 @@ -68,6 +68,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.CallingConvention; @@ -140,14 +141,17 @@ i0, i1, i2, i3, i4, i5, i6, i7}; // @formatter:on + private static final Register[] reservedRegisters = {sp, g0, g2}; + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { Register[] allRegisters = arch.getAvailableValueRegisters(); - Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)]; + Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)]; + List<Register> reservedRegistersList = Arrays.asList(reservedRegisters); int idx = 0; for (Register reg : allRegisters) { - if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) { - // skip g0, stack pointer and thread register + if (reservedRegistersList.contains(reg)) { + // skip reserved registers continue; } if (reserveForHeapBase && reg.equals(g6)) {