--- old/make/autoconf/generated-configure.sh 2018-03-23 16:35:38.614682019 +0000 +++ new/make/autoconf/generated-configure.sh 2018-03-23 16:35:37.974745294 +0000 @@ -5215,7 +5215,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1517244998 +DATE_WHEN_GENERATED=1521480822 ############################################################################### # @@ -55359,7 +55359,7 @@ if test "x$ENABLE_AOT" = "xtrue"; then # Only enable AOT on X64 platforms. - if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then if test -e "${TOPDIR}/src/jdk.aot"; then if test -e "${TOPDIR}/src/jdk.internal.vm.compiler"; then ENABLE_AOT="true" --- old/make/autoconf/hotspot.m4 2018-03-23 16:35:41.474399256 +0000 +++ new/make/autoconf/hotspot.m4 2018-03-23 16:35:40.884457589 +0000 @@ -212,7 +212,7 @@ if test "x$ENABLE_AOT" = "xtrue"; then # Only enable AOT on X64 platforms. - if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then + if test "x$OPENJDK_TARGET_CPU" = "xx86_64" || test "x$OPENJDK_TARGET_CPU" = "xaarch64" ; then if test -e "${TOPDIR}/src/jdk.aot"; then if test -e "${TOPDIR}/src/jdk.internal.vm.compiler"; then ENABLE_AOT="true" --- old/make/hotspot/lib/JvmFeatures.gmk 2018-03-23 16:35:43.204228215 +0000 +++ new/make/hotspot/lib/JvmFeatures.gmk 2018-03-23 16:35:42.604287536 +0000 @@ -152,8 +152,8 @@ # optimization level instead. This activates O3 on slowdebug builds, just # like the old build, but it's probably not right. JVM_OPTIMIZATION := - JVM_CFLAGS_FEATURES += -O3 -flto - JVM_LDFLAGS_FEATURES += -O3 -flto -fuse-linker-plugin -fno-strict-aliasing + JVM_CFLAGS_FEATURES += -O0 -flto + JVM_LDFLAGS_FEATURES += -O0 -flto -fuse-linker-plugin -fno-strict-aliasing endif ifeq ($(call check-jvm-feature, minimal), true) --- old/make/launcher/Launcher-jdk.aot.gmk 2018-03-23 16:35:44.914059151 +0000 +++ new/make/launcher/Launcher-jdk.aot.gmk 2018-03-23 16:35:44.324117483 +0000 @@ -41,6 +41,7 @@ , \ JAVA_ARGS := --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.amd64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ + --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.aarch64=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.hotspot.sparc=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.meta=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ --add-exports=jdk.internal.vm.ci/jdk.vm.ci.runtime=$(call CommaList, jdk.internal.vm.compiler jdk.aot) \ --- old/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp 2018-03-23 16:35:46.203931611 +0000 +++ new/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp 2018-03-23 16:35:45.603990932 +0000 @@ -83,6 +83,61 @@ return 4; // 3 in emit_to_interp_stub + 1 in emit_call } +#if INCLUDE_AOT +#define __ _masm. +void CompiledStaticCall::emit_to_aot_stub(CodeBuffer &cbuf, address mark) { + if (!UseAOT) { + return; + } + // Stub is fixed up when the corresponding call is converted from + // calling compiled code to calling aot code. + // mov r, imm64_aot_code_address + // jmp r + + if (mark == NULL) { + mark = cbuf.insts_mark(); // Get mark within main instrs section. + } + + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a stub. + MacroAssembler _masm(&cbuf); + + address base = + __ start_a_stub(to_aot_stub_size()); + guarantee(base != NULL, "out of space"); + + // Static stub relocation stores the instruction address of the call. + __ relocate(static_stub_Relocation::spec(mark, true /* is_aot */)); + // Load destination AOT code address. + __ movptr(rscratch1, 0); // address is zapped till fixup time. + // This is recognized as unresolved by relocs/nativeinst/ic code. + __ br(rscratch1); + + assert(__ pc() - base <= to_aot_stub_size(), "wrong stub size"); + + // Update current stubs pointer and restore insts_end. + __ end_a_stub(); +} +#undef __ + +int CompiledStaticCall::to_aot_stub_size() { + if (UseAOT) { + return 5 * 4; // movz; movk; movk; movk; br + } else { + return 0; + } +} + +// Relocation entries for call stub, compiled java to aot. +int CompiledStaticCall::reloc_to_aot_stub() { + if (UseAOT) { + return 5 * 4; // movz; movk; movk; movk; br + } else { + return 0; + } +} +#endif // INCLUDE_AOT + void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { address stub = find_stub(false /* is_aot */); guarantee(stub != NULL, "stub not found"); --- old/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp 2018-03-23 16:35:47.483805061 +0000 +++ new/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp 2018-03-23 16:35:46.883864381 +0000 @@ -34,6 +34,9 @@ return pc_offset + NativeCall::instruction_size; } else if (inst->is_general_jump()) { return pc_offset + NativeGeneralJump::instruction_size; + } else if (NativeInstruction::is_adrp_at((address)inst)) { + // adrp; add; blr + return pc_offset + 3 * NativeInstruction::instruction_size; } else { JVMCI_ERROR_0("unsupported type of instruction for call site"); } @@ -80,7 +83,8 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) { address pc = _instructions->start() + pc_offset; NativeInstruction* inst = nativeInstruction_at(pc); - if (inst->is_adr_aligned() || inst->is_ldr_literal()) { + if (inst->is_adr_aligned() || inst->is_ldr_literal() + || (NativeInstruction::maybe_cpool_ref(pc))) { 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); @@ -103,6 +107,10 @@ NativeGeneralJump* jump = nativeGeneralJump_at(pc); jump->set_jump_destination((address) foreign_call_destination); _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); + } else if (NativeInstruction::is_adrp_at((address)inst)) { + // adrp; add; blr + MacroAssembler::pd_patch_instruction_size((address)inst, + (address)foreign_call_destination); } else { JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)); } @@ -125,21 +133,30 @@ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); - call->trampoline_jump(cbuf, SharedRuntime::get_resolve_virtual_call_stub()); + // Don't create trampolines for immutable PIC. + if (!_immutable_pic_compilation) { + call->trampoline_jump(cbuf, SharedRuntime::get_resolve_virtual_call_stub()); + } break; } case INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); - call->trampoline_jump(cbuf, SharedRuntime::get_resolve_static_call_stub()); + // Don't create trampolines for immutable PIC. + if (!_immutable_pic_compilation) { + call->trampoline_jump(cbuf, SharedRuntime::get_resolve_static_call_stub()); + } break; } case INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); - call->trampoline_jump(cbuf, SharedRuntime::get_resolve_opt_virtual_call_stub()); + // Don't create trampolines for immutable PIC. + if (!_immutable_pic_compilation) { + call->trampoline_jump(cbuf, SharedRuntime::get_resolve_opt_virtual_call_stub()); + } break; } default: --- old/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2018-03-23 16:35:48.783676532 +0000 +++ new/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp 2018-03-23 16:35:48.183735853 +0000 @@ -740,7 +740,7 @@ || entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type"); unsigned int start_offset = offset(); - if (far_branches() && !Compile::current()->in_scratch_emit_size()) { + if (UseAOT || (far_branches() && !Compile::current()->in_scratch_emit_size())) { address stub = emit_trampoline_stub(start_offset, entry.target()); if (stub == NULL) { return NULL; // CodeCache is full @@ -749,12 +749,12 @@ if (cbuf) cbuf->set_insts_mark(); relocate(entry.rspec()); - if (!far_branches()) { - bl(entry.target()); - } else { + if (UseAOT || far_branches()) { bl(pc()); + } else { + bl(entry.target()); } - // just need to return a non-null address + return pc(); } @@ -1050,7 +1050,7 @@ } else { vtable_offset_in_bytes += vtable_index.as_constant() * wordSize; ldr(method_result, - form_address(rscratch1, recv_klass, vtable_offset_in_bytes)); + form_address(rscratch1, recv_klass, vtable_offset_in_bytes, 0)); } } --- old/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp 2018-03-23 16:35:50.233533174 +0000 +++ new/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp 2018-03-23 16:35:49.633592495 +0000 @@ -36,7 +36,120 @@ #include "c1/c1_Runtime1.hpp" #endif -void NativeCall::verify() { ; } +void NativeCall::verify() { + assert(NativeCall::is_call_at((address)this), "unexpected code at call site"); +} + +void NativeInstruction::wrote(int offset) { + ICache::invalidate_word(addr_at(offset)); +} + +void NativeLoadGot::report_and_fail() const { + tty->print_cr("Addr: " INTPTR_FORMAT, p2i(instruction_address())); + fatal("not a indirect rip mov to rbx"); +} + +void NativeLoadGot::verify() const { + assert(is_adrp_at((address)this), "must be adrp"); +} + +address NativeLoadGot::got_address() const { + return MacroAssembler::target_addr_for_insn((address)this); +} + +intptr_t NativeLoadGot::data() const { + return *(intptr_t *) got_address(); +} + +address NativePltCall::destination() const { + NativeGotJump* jump = nativeGotJump_at(plt_jump()); + return *(address*)MacroAssembler::target_addr_for_insn((address)jump); +} + +address NativePltCall::plt_entry() const { + return MacroAssembler::target_addr_for_insn((address)this); +} + +address NativePltCall::plt_jump() const { + address entry = plt_entry(); + // Virtual PLT code has move instruction first + if (((NativeGotJump*)entry)->is_GotJump()) { + return entry; + } else { + return nativeLoadGot_at(entry)->next_instruction_address(); + } +} + +address NativePltCall::plt_load_got() const { + address entry = plt_entry(); + if (!((NativeGotJump*)entry)->is_GotJump()) { + // Virtual PLT code has move instruction first + return entry; + } else { + // Static PLT code has move instruction second (from c2i stub) + return nativeGotJump_at(entry)->next_instruction_address(); + } +} + +address NativePltCall::plt_c2i_stub() const { + address entry = plt_load_got(); + // This method should be called only for static calls which has C2I stub. + NativeLoadGot* load = nativeLoadGot_at(entry); + return entry; +} + +address NativePltCall::plt_resolve_call() const { + NativeGotJump* jump = nativeGotJump_at(plt_jump()); + address entry = jump->next_instruction_address(); + if (((NativeGotJump*)entry)->is_GotJump()) { + return entry; + } else { + // c2i stub 2 instructions + entry = nativeLoadGot_at(entry)->next_instruction_address(); + return nativeGotJump_at(entry)->next_instruction_address(); + } +} + +void NativePltCall::reset_to_plt_resolve_call() { + set_destination_mt_safe(plt_resolve_call()); +} + +void NativePltCall::set_destination_mt_safe(address dest) { + // rewriting the value in the GOT, it should always be aligned + NativeGotJump* jump = nativeGotJump_at(plt_jump()); + address* got = (address *) jump->got_address(); + *got = dest; +} + +void NativePltCall::set_stub_to_clean() { + NativeLoadGot* method_loader = nativeLoadGot_at(plt_c2i_stub()); + NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address()); + method_loader->set_data(0); + jump->set_jump_destination((address)-1); +} + +void NativePltCall::verify() const { + assert(NativeCall::is_call_at((address)this), "unexpected code at call site"); +} + +address NativeGotJump::got_address() const { + return MacroAssembler::target_addr_for_insn((address)this); +} + +address NativeGotJump::destination() const { + address *got_entry = (address *) got_address(); + return *got_entry; +} + +bool NativeGotJump::is_GotJump() const { + NativeInstruction *insn = + nativeInstruction_at(addr_at(3 * NativeInstruction::instruction_size)); + return insn->encoding() == 0xd61f0200; // br x16 +} + +void NativeGotJump::verify() const { + assert(is_adrp_at((address)this), "must be adrp"); +} address NativeCall::destination() const { address addr = (address)this; @@ -103,9 +216,11 @@ is_NativeCallTrampolineStub_at(bl_destination)) return bl_destination; - // If the codeBlob is not a nmethod, this is because we get here from the - // CodeBlob constructor, which is called within the nmethod constructor. - return trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + if (code->is_nmethod()) { + return trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code); + } + + return NULL; } // Inserts a native call instruction at a given pc @@ -388,3 +503,4 @@ return stub; } + --- old/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp 2018-03-23 16:35:51.533404646 +0000 +++ new/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp 2018-03-23 16:35:50.933463966 +0000 @@ -96,6 +96,8 @@ void set_ptr_at (int offset, address ptr) { *(address*) addr_at(offset) = ptr; } void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; } + void wrote(int offset); + public: // unit test stuff @@ -142,6 +144,46 @@ return (NativeInstruction*)address; } +class NativePltCall: public NativeInstruction { +public: + enum Intel_specific_constants { + instruction_size = 4, + instruction_offset = 0, + displacement_offset = 1, + return_address_offset = 4 + }; + address instruction_address() const { return addr_at(instruction_offset); } + address next_instruction_address() const { return addr_at(return_address_offset); } + address displacement_address() const { return addr_at(displacement_offset); } + int displacement() const { return (jint) int_at(displacement_offset); } + address return_address() const { return addr_at(return_address_offset); } + address destination() const; + address plt_entry() const; + address plt_jump() const; + address plt_load_got() const; + address plt_resolve_call() const; + address plt_c2i_stub() const; + void set_stub_to_clean(); + + void reset_to_plt_resolve_call(); + void set_destination_mt_safe(address dest); + + void verify() const; +}; + +inline NativePltCall* nativePltCall_at(address address) { + NativePltCall* call = (NativePltCall*) address; +#ifdef ASSERT + call->verify(); +#endif + return call; +} + +inline NativePltCall* nativePltCall_before(address addr) { + address at = addr - NativePltCall::instruction_size; + return nativePltCall_at(at); +} + inline NativeCall* nativeCall_at(address address); // The NativeCall is an abstraction for accessing/manipulating native // call instructions (used to manipulate inline caches, primitive & @@ -163,7 +205,7 @@ address return_address() const { return addr_at(return_address_offset); } address destination() const; - void set_destination(address dest) { + void set_destination(address dest) { int offset = dest - instruction_address(); unsigned int insn = 0b100101 << 26; assert((offset & 3) == 0, "should be"); @@ -185,6 +227,12 @@ return is_call_at(return_address - NativeCall::return_address_offset); } +#if INCLUDE_AOT + static bool is_far_call(address instr, address target) { + return Assembler::reachable_from_branch_at(instr, target); + } +#endif + // MT-safe patching of a call instruction. static void insert(address code_pos, address entry); @@ -375,6 +423,39 @@ static void test() {} }; +// adrp x16, #page +// add x16, x16, #offset +// ldr x16, [x16] +class NativeLoadGot: public NativeInstruction { +public: + enum AArch64_specific_constants { + instruction_length = 4 * NativeInstruction::instruction_size, + offset_offset = 0, + }; + + address instruction_address() const { return addr_at(0); } + address return_address() const { return addr_at(instruction_length); } + address got_address() const; + address next_instruction_address() const { return return_address(); } + intptr_t data() const; + void set_data(intptr_t data) { + intptr_t *addr = (intptr_t *) got_address(); + *addr = data; + } + + void verify() const; +private: + void report_and_fail() const; +}; + +inline NativeLoadGot* nativeLoadGot_at(address addr) { + NativeLoadGot* load = (NativeLoadGot*) addr; +#ifdef ASSERT + load->verify(); +#endif + return load; +} + class NativeJump: public NativeInstruction { public: enum AArch64_specific_constants { @@ -435,6 +516,31 @@ return jump; } +class NativeGotJump: public NativeInstruction { +public: + enum AArch64_specific_constants { + instruction_size = 4 * NativeInstruction::instruction_size, + }; + + void verify() const; + address instruction_address() const { return addr_at(0); } + address destination() const; + address return_address() const { return addr_at(instruction_size); } + address got_address() const; + address next_instruction_address() const { return addr_at(instruction_size); } + bool is_GotJump() const; + + void set_jump_destination(address dest) { + address* got = (address *)got_address(); + *got = dest; + } +}; + +inline NativeGotJump* nativeGotJump_at(address addr) { + NativeGotJump* jump = (NativeGotJump*)(addr); + return jump; +} + class NativePopReg : public NativeInstruction { public: // Insert a pop instruction --- old/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp 2018-03-23 16:35:52.843275129 +0000 +++ new/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp 2018-03-23 16:35:52.243334449 +0000 @@ -559,7 +559,7 @@ __ ldr(rscratch1, Address(rmethod, in_bytes(Method::from_compiled_offset()))); #if INCLUDE_JVMCI - if (EnableJVMCI) { + if (EnableJVMCI || UseAOT) { // check if this call should be routed towards a specific entry point __ ldr(rscratch2, Address(rthread, in_bytes(JavaThread::jvmci_alternate_call_target_offset()))); Label no_alternative_target; @@ -2299,7 +2299,7 @@ // Setup code generation tools int pad = 0; #if INCLUDE_JVMCI - if (EnableJVMCI) { + if (EnableJVMCI || UseAOT) { pad += 512; // Increase the buffer size when compiling for JVMCI } #endif @@ -2381,7 +2381,7 @@ int implicit_exception_uncommon_trap_offset = 0; int uncommon_trap_offset = 0; - if (EnableJVMCI) { + if (EnableJVMCI || UseAOT) { implicit_exception_uncommon_trap_offset = __ pc() - start; __ ldr(lr, Address(rthread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset()))); @@ -2507,7 +2507,7 @@ __ reset_last_Java_frame(false); #if INCLUDE_JVMCI - if (EnableJVMCI) { + if (EnableJVMCI || UseAOT) { __ bind(after_fetch_unroll_info_call); } #endif @@ -2665,7 +2665,7 @@ _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); #if INCLUDE_JVMCI - if (EnableJVMCI) { + if (EnableJVMCI || UseAOT) { _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset); _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset); } --- old/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2018-03-23 16:35:54.233137702 +0000 +++ new/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp 2018-03-23 16:35:53.633197023 +0000 @@ -481,7 +481,7 @@ #if INCLUDE_JVMCI // Check if we need to take lock at entry of synchronized method. This can // only occur on method entry so emit it only for vtos with step 0. - if (EnableJVMCI && state == vtos && step == 0) { + if ((EnableJVMCI || UseAOT) && state == vtos && step == 0) { Label L; __ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset())); __ cbz(rscratch1, L); --- old/src/hotspot/share/code/compiledIC.cpp 2018-03-23 16:35:55.583004231 +0000 +++ new/src/hotspot/share/code/compiledIC.cpp 2018-03-23 16:35:54.983063552 +0000 @@ -691,7 +691,9 @@ } void CompiledIC::print_compiled_ic() { - tty->print("Inline cache at " INTPTR_FORMAT ", calling %s " INTPTR_FORMAT " cached_value " INTPTR_FORMAT, + const char *opt = is_optimized() ? "opt " : ""; + tty->print("%sInline cache at " INTPTR_FORMAT ", calling %s " INTPTR_FORMAT " cached_value " INTPTR_FORMAT, + opt, p2i(instruction_address()), is_call_to_interpreted() ? "interpreted " : "", p2i(ic_destination()), p2i(is_optimized() ? NULL : cached_value())); } --- old/src/hotspot/share/code/oopRecorder.hpp 2018-03-23 16:35:56.892874714 +0000 +++ new/src/hotspot/share/code/oopRecorder.hpp 2018-03-23 16:35:56.292934035 +0000 @@ -211,7 +211,7 @@ return _oops.is_real(h); } - int allocate_metadata_index(Metadata* oop) { + virtual int allocate_metadata_index(Metadata* oop) { return _metadata.allocate_index(oop); } virtual int find_index(Metadata* h) { --- old/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp 2018-03-23 16:35:58.182747174 +0000 +++ new/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp 2018-03-23 16:35:57.582806495 +0000 @@ -175,7 +175,7 @@ } AOTOopRecorder::AOTOopRecorder(Arena* arena, bool deduplicate) : OopRecorder(arena, deduplicate) { - _meta_refs = new GrowableArray(); + _meta_refs = new GrowableArray(64); } int AOTOopRecorder::nr_meta_refs() const { @@ -1184,7 +1184,8 @@ TRACE_jvmci_3("method call"); CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, CHECK); - if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) { + if ((_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) + && !_immutable_pic_compilation) { // Need a static call stub for transitions from compiled to interpreted. CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset); } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java 2018-03-23 16:35:59.552611725 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java 2018-03-23 16:35:58.922674012 +0000 @@ -526,7 +526,7 @@ switch (osName) { case "Linux": case "SunOS": - JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName); + JELFRelocObject elfobj = JELFRelocObject.newInstance(this, outputFileName); elfobj.createELFRelocObject(relocationTable, symbolTable.values()); break; case "Mac OS X": @@ -574,7 +574,7 @@ * @param info relocation information to be added */ public void addRelocation(Relocation info) { - // System.out.println("# Relocation [" + symName + "] [" + info.getOffset() + "] [" + + // System.out.println("# Relocation [" + info.getSymbol() + "] [" + info.getOffset() + "] [" + // info.getSection().getContainerName() + "] [" + info.getSymbol().getName() + "] [" + // info.getSymbol().getOffset() + " @ " + info.getSymbol().getSection().getContainerName() + // "]"); --- old/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java 2018-03-23 16:36:00.872481220 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java 2018-03-23 16:36:00.242543507 +0000 @@ -208,12 +208,26 @@ /** * Relocation types */ + static final int R_X86_64_NONE = 0x0; static final int R_X86_64_64 = 0x1; static final int R_X86_64_PC32 = 0x2; static final int R_X86_64_PLT32 = 0x4; static final int R_X86_64_GOTPCREL = 0x9; + static final int R_AARCH64_NONE = 256; + static final int R_AARCH64_ABS64 = 257; + static final int R_AARCH64_CALL26 = 283; + static final int R_AARCH64_ADR_GOT_PAGE = 311; + static final int R_AARCH64_LD64_GOT_LO12_NC = 312; + + static final int R_AARCH64_MOVW_UABS_G0_NC = 264; + static final int R_AARCH64_MOVW_UABS_G1_NC = 266; + static final int R_AARCH64_MOVW_UABS_G2_NC = 268; + + static final int R_AARCH64_ADR_PREL_PG_HI21 = 275; + static final int R_AARCH64_ADD_ABS_LO12_NC = 277; + static final int R_AARCH64_LDST64_ABS_LO12_NC = 286; } /** @@ -240,6 +254,20 @@ static final int R_X86_64_PLT32 = 0x4; static final int R_X86_64_GOTPCREL = 0x9; + static final int R_AARCH64_NONE = 256; + static final int R_AARCH64_ABS64 = 257; + static final int R_AARCH64_CALL26 = 283; + static final int R_AARCH64_ADR_GOT_PAGE = 311; + static final int R_AARCH64_LD64_GOT_LO12_NC = 312; + + static final int R_AARCH64_MOVW_UABS_G0_NC = 264; + static final int R_AARCH64_MOVW_UABS_G1_NC = 266; + static final int R_AARCH64_MOVW_UABS_G2_NC = 268; + + static final int R_AARCH64_ADR_PREL_PG_HI21 = 275; + static final int R_AARCH64_ADD_ABS_LO12_NC = 277; + static final int R_AARCH64_LDST64_ABS_LO12_NC = 286; + static long ELF64_R_INFO(int symidx, int type) { return (((long)symidx << 32) + type); } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java 2018-03-23 16:36:02.162353680 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java 2018-03-23 16:36:01.532415967 +0000 @@ -55,6 +55,8 @@ if (archStr.equals("amd64") || archStr.equals("x86_64")) { arch = Elf64_Ehdr.EM_X86_64; + } else if (archStr.equals("amd64") || archStr.equals("aarch64")) { + arch = Elf64_Ehdr.EM_AARCH64; } else { System.out.println("Unsupported architecture " + archStr); arch = Elf64_Ehdr.EM_NONE; --- old/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java 2018-03-23 16:36:03.452226141 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java 2018-03-23 16:36:02.822288427 +0000 @@ -46,7 +46,7 @@ import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; -public class JELFRelocObject { +public abstract class JELFRelocObject { private final BinaryContainer binContainer; @@ -54,12 +54,22 @@ private final int segmentSize; - public JELFRelocObject(BinaryContainer binContainer, String outputFileName) { + protected JELFRelocObject(BinaryContainer binContainer, String outputFileName) { this.binContainer = binContainer; this.elfContainer = new ElfContainer(outputFileName); this.segmentSize = binContainer.getCodeSegmentSize(); } + public static JELFRelocObject newInstance(BinaryContainer binContainer, String outputFileName) { + String archStr = System.getProperty("os.arch").toLowerCase(); + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + return new AMD64JELFRelocObject(binContainer, outputFileName); + } else if (archStr.equals("aarch64")) { + return new AArch64JELFRelocObject(binContainer, outputFileName); + } + throw new InternalError("Unsupported platform: " + archStr); + } + private static ElfSection createByteSection(ArrayList sections, String sectName, byte[] scnData, @@ -295,75 +305,6 @@ return (elfRelocTable); } - private static void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { - RelocType relocType = reloc.getType(); - - int elfRelocType = getELFRelocationType(relocType); - ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol(); - int symno = sym.getIndex(); - int sectindex = reloc.getSection().getSectionId(); - int offset = reloc.getOffset(); - int addend = 0; - - switch (relocType) { - case JAVA_CALL_DIRECT: - case STUB_CALL_DIRECT: - case FOREIGN_CALL_INDIRECT_GOT: { - // Create relocation entry - addend = -4; // Size in bytes of the patch location - // Relocation should be applied at the location after call operand - offset = offset + reloc.getSize() + addend; - break; - } - case JAVA_CALL_INDIRECT: - case METASPACE_GOT_REFERENCE: - case EXTERNAL_PLT_TO_GOT: { - addend = -4; // Size of 32-bit address of the GOT - /* - * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads the address of - * polling page. So set the offset appropriately. - */ - offset = offset + addend; - break; - } - case EXTERNAL_GOT_TO_PLT: { - // this is load time relocations - break; - } - default: - throw new InternalError("Unhandled relocation type: " + relocType); - } - elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); - } - - private static int getELFRelocationType(RelocType relocType) { - int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH - switch (ElfTargetInfo.getElfArch()) { - case Elf64_Ehdr.EM_X86_64: - // Return R_X86_64_* entries based on relocType - if (relocType == RelocType.JAVA_CALL_DIRECT || - relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { - elfRelocType = Elf64_Rela.R_X86_64_PLT32; - } else if (relocType == RelocType.STUB_CALL_DIRECT) { - elfRelocType = Elf64_Rela.R_X86_64_PC32; - } else if (relocType == RelocType.JAVA_CALL_INDIRECT) { - elfRelocType = Elf64_Rela.R_X86_64_NONE; - } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || - relocType == RelocType.EXTERNAL_PLT_TO_GOT) { - elfRelocType = Elf64_Rela.R_X86_64_PC32; - } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) { - elfRelocType = Elf64_Rela.R_X86_64_64; - } else { - assert false : "Unhandled relocation type: " + relocType; - } - break; - default: - System.out.println("Relocation Type mapping: Unhandled architecture"); - } - return elfRelocType; - } - private static void createElfRelocSections(ArrayList sections, ElfRelocTable elfRelocTable, int symtabsectidx) { @@ -383,4 +324,7 @@ } } } + + abstract void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable); + } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java 2018-03-23 16:36:04.762096624 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java 2018-03-23 16:36:04.132158910 +0000 @@ -439,6 +439,12 @@ static String metadataName(HotSpotResolvedObjectType type) { AOTKlassData data = getAOTKlassData(type); assert data != null : "no data for " + type; + try { + AOTKlassData t = getAOTKlassData(type); + t.getMetadataName(); + } catch (NullPointerException e) { + return type.getName(); + } return getAOTKlassData(type).getMetadataName(); } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java 2018-03-23 16:36:06.051969084 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CodeSectionProcessor.java 2018-03-23 16:36:05.422031371 +0000 @@ -32,6 +32,8 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.site.Call; import jdk.vm.ci.code.site.Infopoint; @@ -72,7 +74,8 @@ for (Infopoint infopoint : compResult.getInfopoints()) { if (infopoint.reason == InfopointReason.CALL) { final Call callInfopoint = (Call) infopoint; - if (callInfopoint.target instanceof HotSpotForeignCallLinkage) { + if (callInfopoint.target instanceof HotSpotForeignCallLinkage && + target.arch instanceof AMD64) { // TODO 4 is x86 size of relative displacement. // For SPARC need something different. int destOffset = infopoint.pcOffset + callInfopoint.size - 4; --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java 2018-03-23 16:36:07.341841545 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CompiledMethodInfo.java 2018-03-23 16:36:06.711903831 +0000 @@ -39,6 +39,8 @@ final class CompiledMethodInfo { + static final String archStr = System.getProperty("os.arch").toLowerCase(); + private static final int UNINITIALIZED_OFFSET = -1; private static class AOTMethodOffsets { @@ -304,10 +306,18 @@ boolean hasMark(Site call, MarkId id) { for (Mark m : compilationResult.getMarks()) { - // TODO: X64-specific code. - // Call instructions are aligned to 8 - // bytes - 1 on x86 to patch address atomically, - int adjOffset = (m.pcOffset & (-8)) + 7; + int adjOffset = m.pcOffset; + if (archStr.equals("aarch64")) { + // FIXME: This is very ugly. + // The mark is at the end of a group of three instructions: + // adrp; add; ldr + adjOffset += 12; + } else { + // TODO: X64-specific code. + // Call instructions are aligned to 8 + // bytes - 1 on x86 to patch address atomically, + adjOffset = (adjOffset & (-8)) + 7; + } // Mark points before aligning nops. if ((call.pcOffset == adjOffset) && MarkId.getEnum((int) m.id) == id) { return true; --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java 2018-03-23 16:36:08.641713016 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/ELFMacroAssembler.java 2018-03-23 16:36:08.011775303 +0000 @@ -25,8 +25,10 @@ import jdk.tools.jaotc.StubInformation; import jdk.tools.jaotc.amd64.AMD64ELFMacroAssembler; +import jdk.tools.jaotc.aarch64.AArch64ELFMacroAssembler; import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.TargetDescription; @@ -35,7 +37,9 @@ public static ELFMacroAssembler getELFMacroAssembler(TargetDescription target) { Architecture architecture = target.arch; if (architecture instanceof AMD64) { - return new AMD64ELFMacroAssembler(target); + return new AMD64ELFMacroAssembler(target); + } else if (architecture instanceof AArch64) { + return new AArch64ELFMacroAssembler(target); } else { throw new InternalError("Unsupported architecture " + architecture); } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java 2018-03-23 16:36:09.921586465 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/InstructionDecoder.java 2018-03-23 16:36:09.291648752 +0000 @@ -24,8 +24,10 @@ package jdk.tools.jaotc; import jdk.tools.jaotc.amd64.AMD64InstructionDecoder; +import jdk.tools.jaotc.aarch64.AArch64InstructionDecoder; import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.TargetDescription; @@ -35,6 +37,8 @@ Architecture architecture = target.arch; if (architecture instanceof AMD64) { return new AMD64InstructionDecoder(target); + } else if (architecture instanceof AArch64) { + return new AArch64InstructionDecoder(target); } else { throw new InternalError("Unsupported architecture " + architecture); } --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java 2018-03-23 16:36:11.201459915 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java 2018-03-23 16:36:10.571522201 +0000 @@ -38,7 +38,19 @@ private static final byte[] zeroSlot = new byte[8]; // -1 represents Universe::non_oop_word() value - private static final byte[] minusOneSlot = {-1, -1, -1, -1, -1, -1, -1, -1}; + private static final byte[] minusOneSlot; + + static { + String archStr = System.getProperty("os.arch").toLowerCase(); + if (archStr.equals("aarch64")) { + // AArch64 is a special case: it uses 48-bit addresses. + byte[] non_oop_word = {-1, -1, -1, -1, -1, -1, 0, 0}; + minusOneSlot = non_oop_word; + } else { + byte[] non_oop_word = {-1, -1, -1, -1, -1, -1, -1, -1}; + minusOneSlot = non_oop_word; + } + } JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) { super(createPltEntrySymbol(binaryContainer, mi, call, callSiteRelocation)); @@ -123,6 +135,7 @@ */ private static String getResolveSymbolName(CompiledMethodInfo mi, Call call) { String resolveSymbolName; + String name = call.target.toString(); if (CallInfo.isStaticCall(call)) { assert mi.hasMark(call, MarkId.INVOKESTATIC); resolveSymbolName = BinaryContainer.getResolveStaticEntrySymbolName(); --- old/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java 2018-03-23 16:36:12.491332375 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java 2018-03-23 16:36:11.861394662 +0000 @@ -130,7 +130,7 @@ throw new InternalError(errorMessage); } File objFile = new File(objectFileName); - if (objFile.exists()) { + if (objFile.exists() && System.getenv("DO_NOT_DELETE_PRECIOUS_FILE") == null) { if (!objFile.delete()) { throw new InternalError("Failed to delete " + objectFileName + " file"); } --- old/src/jdk.internal.vm.compiler/share/classes/module-info.java 2018-03-23 16:36:13.791203847 +0000 +++ new/src/jdk.internal.vm.compiler/share/classes/module-info.java 2018-03-23 16:36:13.151267122 +0000 @@ -43,6 +43,7 @@ exports org.graalvm.compiler.api.runtime to jdk.aot; exports org.graalvm.compiler.api.replacements to jdk.aot; exports org.graalvm.compiler.asm.amd64 to jdk.aot; + exports org.graalvm.compiler.asm.aarch64 to jdk.aot; exports org.graalvm.compiler.bytecode to jdk.aot; exports org.graalvm.compiler.code to jdk.aot; exports org.graalvm.compiler.core to jdk.aot; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2018-03-23 16:36:15.081076307 +0000 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java 2018-03-23 16:36:14.441139583 +0000 @@ -26,6 +26,7 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADRP; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.AND; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ANDS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ASRV; @@ -1316,15 +1317,13 @@ /** * Address of page: sign extends 21-bit offset, shifts if left by 12 and adds it to the value of * the PC with its bottom 12-bits cleared, writing the result to dst. + * No offset is emiited; the instruction will be patched later. * * @param dst general purpose register. May not be null, zero-register or stackpointer. - * @param imm Signed 33-bit offset with lower 12bits clear. */ - // protected void adrp(Register dst, long imm) { - // assert (imm & NumUtil.getNbitNumberInt(12)) == 0 : "Lower 12-bit of immediate must be zero."; - // assert NumUtil.isSignedNbit(33, imm); - // addressCalculationInstruction(dst, (int) (imm >>> 12), Instruction.ADRP); - // } + public void adrp(Register dst) { + emitInt(ADRP.encoding | PcRelImmOp | rd(dst) ); + } /** * Adds a 21-bit signed offset to the program counter and writes the result to dst. @@ -1340,6 +1339,10 @@ emitInt(ADR.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(imm21), pos); } + public void adrp(Register dst, int pageOffset) { + emitInt(ADRP.encoding | PcRelImmOp | rd(dst) | getPcRelativeImmEncoding(pageOffset)); + } + private static int getPcRelativeImmEncoding(int imm21) { assert NumUtil.isSignedNbit(21, imm21); int imm = imm21 & NumUtil.getNbitNumberInt(21); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2018-03-23 16:36:16.460939870 +0000 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java 2018-03-23 16:36:15.821003145 +0000 @@ -1564,6 +1564,12 @@ return AArch64Address.PLACEHOLDER; } + public void addressOf(Register dst) { + // This will be fixed up later. + super.adrp(dst); + super.add(64, dst, dst, 0); + } + /** * Loads an address into Register d. * --- /dev/null 2018-03-13 15:07:55.880000000 +0000 +++ new/src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp 2018-03-23 16:36:17.170869673 +0000 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "aot/compiledIC_aot.hpp" +#include "code/codeCache.hpp" +#include "memory/resourceArea.hpp" + +void CompiledDirectStaticCall::set_to_far(const methodHandle& callee, address entry) { + if (TraceICs) { + ResourceMark rm; + tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_far %s", + p2i(instruction_address()), + callee->name_and_sig_as_C_string()); + } + + set_destination_mt_safe(entry); +} + +void CompiledPltStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { + address stub = find_stub(); + guarantee(stub != NULL, "stub not found"); + if (TraceICs) { + ResourceMark rm; + tty->print_cr("CompiledPltStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", + p2i(instruction_address()), + callee->name_and_sig_as_C_string()); + } + + // Creation also verifies the object. + NativeLoadGot* method_loader = nativeLoadGot_at(stub); + NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address()); + + intptr_t data = method_loader->data(); + address destination = jump->destination(); + assert(data == 0 || data == (intptr_t)callee(), + "a) MT-unsafe modification of inline cache"); + assert(destination == (address)Universe::non_oop_word() + || destination == entry, + "b) MT-unsafe modification of inline cache"); + + // Update stub. + method_loader->set_data((intptr_t)callee()); + jump->set_jump_destination(entry); + + // Update jump to call. + set_destination_mt_safe(stub); +} + +#ifdef NEVER_CALLED +void CompiledPltStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { + assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); + // Reset stub. + address stub = static_stub->addr(); + assert(stub != NULL, "stub not found"); + // Creation also verifies the object. + NativeLoadGot* method_loader = nativeLoadGot_at(stub); + NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address()); + method_loader->set_data(0); + jump->set_jump_destination((address)-1); +} +#endif + +#ifndef PRODUCT +void CompiledPltStaticCall::verify() { + // Verify call. + _call->verify(); + +#ifdef ASSERT + CodeBlob *cb = CodeCache::find_blob_unsafe((address) _call); + assert(cb && cb->is_aot(), "CompiledPltStaticCall can only be used on AOTCompiledMethod"); +#endif + + // Verify stub. + address stub = find_stub(); + assert(stub != NULL, "no stub found for static call"); + // Creation also verifies the object. + NativeLoadGot* method_loader = nativeLoadGot_at(stub); + NativeGotJump* jump = nativeGotJump_at(method_loader->next_instruction_address()); + // Verify state. + assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check"); +} +#endif // !PRODUCT --- /dev/null 2018-03-13 15:07:55.880000000 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java 2018-03-23 16:36:18.530735213 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; + + +public class AArch64JELFRelocObject extends JELFRelocObject { + + AArch64JELFRelocObject(BinaryContainer binContainer, String outputFileName) { + super(binContainer, outputFileName); + } + + void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { + RelocType relocType = reloc.getType(); + + int elfRelocType = getELFRelocationType(relocType); + ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; + + switch (relocType) { + case STUB_CALL_DIRECT: + case JAVA_CALL_DIRECT: { + break; + } + case EXTERNAL_PLT_TO_GOT: + offset -= 16; + elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend); + elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend); + return; + + case FOREIGN_CALL_INDIRECT_GOT: { + break; + } + case METASPACE_GOT_REFERENCE: { + offset -= 4; + + elfRelocTable.createRelocationEntry(sectindex, offset, symno, Elf64_Rela.R_AARCH64_ADR_PREL_PG_HI21, addend); + elfRelocTable.createRelocationEntry(sectindex, offset + 4, symno, Elf64_Rela.R_AARCH64_ADD_ABS_LO12_NC, addend); + return; + } + // break; + case JAVA_CALL_INDIRECT: { + addend = -4; + offset = offset + addend; + break; + } + case EXTERNAL_GOT_TO_PLT: { + // this is load time relocations + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + + elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); + } + + int getELFRelocationType(RelocType relocType) { + int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH + switch (ElfTargetInfo.getElfArch()) { + case Elf64_Ehdr.EM_AARCH64: + // Return R_X86_64_* entries based on relocType + if (relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + elfRelocType = Elf64_Rela.R_AARCH64_CALL26; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + elfRelocType = Elf64_Rela.R_AARCH64_CALL26; + } else if (relocType == RelocType.JAVA_CALL_INDIRECT) { + elfRelocType = Elf64_Rela.R_AARCH64_CALL26; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT) { + elfRelocType = Elf64_Rela.R_AARCH64_NONE; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) { + elfRelocType = Elf64_Rela.R_AARCH64_ABS64; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + + default: + System.out.println("Relocation Type mapping: Unhandled architecture: " + + ElfTargetInfo.getElfArch()); + } + return elfRelocType; + } +} --- /dev/null 2018-03-13 15:07:55.880000000 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java 2018-03-23 16:36:19.910598775 +0000 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; + + +public class AMD64JELFRelocObject extends JELFRelocObject { + + AMD64JELFRelocObject(BinaryContainer binContainer, String outputFileName) { + super(binContainer, outputFileName); + } + + protected void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { + RelocType relocType = reloc.getType(); + + int elfRelocType = getELFRelocationType(relocType); + ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; + + switch (relocType) { + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + break; + } + case JAVA_CALL_INDIRECT: + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: { + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * reloc.getOffset() points to the test instruction after the instruction that loads the address of + * polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case EXTERNAL_GOT_TO_PLT: { + // this is load time relocations + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); + } + + private int getELFRelocationType(RelocType relocType) { + int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH + switch (ElfTargetInfo.getElfArch()) { + case Elf64_Ehdr.EM_X86_64: + // Return R_X86_64_* entries based on relocType + if (relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PLT32; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + elfRelocType = Elf64_Rela.R_X86_64_PC32; + } else if (relocType == RelocType.JAVA_CALL_INDIRECT) { + elfRelocType = Elf64_Rela.R_X86_64_NONE; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PC32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) { + elfRelocType = Elf64_Rela.R_X86_64_64; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + + default: + System.out.println("Relocation Type mapping: Unhandled architecture: " + + ElfTargetInfo.getElfArch()); + } + return elfRelocType; + } +} --- /dev/null 2018-03-13 15:07:55.880000000 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java 2018-03-23 16:36:21.280463326 +0000 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.aarch64; + +import jdk.tools.jaotc.StubInformation; +import jdk.tools.jaotc.ELFMacroAssembler; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; + + +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.code.Register; + +import static jdk.vm.ci.aarch64.AArch64.*; + +public final class AArch64ELFMacroAssembler extends AArch64MacroAssembler implements ELFMacroAssembler { + + private int currentEndOfInstruction; + + public AArch64ELFMacroAssembler(TargetDescription target) { + super(target); + } + + @Override + public int currentEndOfInstruction() { + return currentEndOfInstruction; + } + + @Override + public byte[] getPLTJumpCode() { + // The main dispatch instruction + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + + currentEndOfInstruction = position(); + + align(8); + + return close(true); + } + + @Override + public byte[] getPLTStaticEntryCode(StubInformation stub) { + // The main dispatch instruction + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + stub.setDispatchJumpOffset(position()); + + // C2I stub used to call interpreter. First load r12 + // (i.e. rmethod) with a pointer to the Method structure ... + addressOf(r12); + ldr(64, r12, AArch64Address.createBaseRegisterOnlyAddress(r12)); + nop(); + stub.setMovOffset(position()); + + // ... then jump to the interpreter. + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + stub.setC2IJumpOffset(position()); + + // Call to VM runtime to resolve the call. + stub.setResolveJumpStart(position()); + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + stub.setResolveJumpOffset(position()); + currentEndOfInstruction = position(); + + align(8); + stub.setSize(position()); + + return close(true); + } + + @Override + public byte[] getPLTVirtualEntryCode(StubInformation stub) { + // Fixup an inline cache. + // Load r9 with a pointer to the Klass. + addressOf(r17); + ldr(64, r9, AArch64Address.createBaseRegisterOnlyAddress(r17)); + nop(); + stub.setMovOffset(position()); + + // Jump to the method. + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + stub.setDispatchJumpOffset(position()); + + // Call to VM runtime to resolve the call. + stub.setResolveJumpStart(position()); + addressOf(r16); + ldr(64, r16, AArch64Address.createBaseRegisterOnlyAddress(r16)); + jmp(r16); + stub.setResolveJumpOffset(position()); + currentEndOfInstruction = position(); + + align(8); + stub.setSize(position()); + + return close(true); + } +} --- /dev/null 2018-03-13 15:07:55.880000000 +0000 +++ new/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java 2018-03-23 16:36:22.650327877 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.aarch64; + +import jdk.tools.jaotc.InstructionDecoder; + +import jdk.vm.ci.code.TargetDescription; + +public final class AArch64InstructionDecoder extends InstructionDecoder { + + private int currentEndOfInstruction; + + public AArch64InstructionDecoder(TargetDescription target) { + } + + @Override + public int currentEndOfInstruction() { + return currentEndOfInstruction; + } + + @Override + public void decodePosition(final byte[] code, int pcOffset) { + currentEndOfInstruction = pcOffset + 4; + } +}