8185505: AArch64: Port AOT to AArch64
Reviewed-by: kvn
This commit is contained in:
parent
3222e19f2c
commit
0d6885f792
make
src
hotspot
cpu/aarch64
compiledIC_aarch64.cppcompiledIC_aot_aarch64.cppjvmciCodeInstaller_aarch64.cppnativeInst_aarch64.cppnativeInst_aarch64.hppsharedRuntime_aarch64.cpptemplateInterpreterGenerator_aarch64.cpp
share
jdk.aot/share/classes
jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat
jdk.tools.jaotc/src/jdk/tools/jaotc
jdk.internal.vm.compiler/share/classes
module-info.java
org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64
@ -206,7 +206,7 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_AOT],
|
||||
|
||||
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"
|
||||
|
@ -128,8 +128,9 @@ endif
|
||||
ifneq ($(call check-jvm-feature, aot), true)
|
||||
JVM_CFLAGS_FEATURES += -DINCLUDE_AOT=0
|
||||
JVM_EXCLUDE_FILES += \
|
||||
compiledIC_aot_x86_64.cpp compilerRuntime.cpp \
|
||||
aotCodeHeap.cpp aotCompiledMethod.cpp aotLoader.cpp compiledIC_aot.cpp
|
||||
compiledIC_aot_x86_64.cpp compiledIC_aot_aarch64.cpp \
|
||||
compilerRuntime.cpp aotCodeHeap.cpp aotCompiledMethod.cpp \
|
||||
aotLoader.cpp compiledIC_aot.cpp
|
||||
endif
|
||||
|
||||
ifneq ($(call check-jvm-feature, cmsgc), true)
|
||||
|
@ -41,6 +41,7 @@ $(eval $(call SetupBuildLauncher, jaotc, \
|
||||
, \
|
||||
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) \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Red Hat Inc. 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
|
||||
@ -56,8 +56,17 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
|
||||
}
|
||||
// static stub relocation stores the instruction address of the call
|
||||
__ relocate(static_stub_Relocation::spec(mark));
|
||||
// static stub relocation also tags the Method* in the code-stream.
|
||||
|
||||
#if INCLUDE_AOT
|
||||
// Don't create a Metadata reloc if we're generating immutable PIC.
|
||||
if (cbuf.immutable_PIC()) {
|
||||
__ movptr(rmethod, 0);
|
||||
} else {
|
||||
__ mov_metadata(rmethod, (Metadata*)NULL);
|
||||
}
|
||||
#else
|
||||
__ mov_metadata(rmethod, (Metadata*)NULL);
|
||||
#endif
|
||||
__ movptr(rscratch1, 0);
|
||||
__ br(rscratch1);
|
||||
|
||||
@ -83,6 +92,61 @@ int CompiledStaticCall::reloc_to_interp_stub() {
|
||||
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");
|
||||
|
103
src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp
Normal file
103
src/hotspot/cpu/aarch64/compiledIC_aot_aarch64.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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
|
@ -35,6 +35,9 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand
|
||||
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");
|
||||
}
|
||||
@ -81,7 +84,8 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, T
|
||||
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);
|
||||
@ -104,6 +108,10 @@ void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong forei
|
||||
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));
|
||||
}
|
||||
|
@ -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;
|
||||
@ -71,6 +184,7 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
|
||||
ResourceMark rm;
|
||||
int code_size = NativeInstruction::instruction_size;
|
||||
address addr_call = addr_at(0);
|
||||
bool reachable = Assembler::reachable_from_branch_at(addr_call, dest);
|
||||
assert(NativeCall::is_call_at(addr_call), "unexpected code at call site");
|
||||
|
||||
// Patch the constant in the call's trampoline stub.
|
||||
@ -81,7 +195,7 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
|
||||
}
|
||||
|
||||
// Patch the call.
|
||||
if (Assembler::reachable_from_branch_at(addr_call, dest)) {
|
||||
if (reachable) {
|
||||
set_destination(dest);
|
||||
} else {
|
||||
assert (trampoline_stub_addr != NULL, "we need a trampoline");
|
||||
@ -103,9 +217,11 @@ address NativeCall::get_trampoline() {
|
||||
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
|
||||
@ -340,9 +456,16 @@ void NativeIllegalInstruction::insert(address code_pos) {
|
||||
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
||||
|
||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
||||
assert(nativeInstruction_at(verified_entry)->is_jump_or_nop()
|
||||
|| nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(),
|
||||
"Aarch64 cannot replace non-jump with jump");
|
||||
|
||||
#ifdef ASSERT
|
||||
// This may be the temporary nmethod generated while we're AOT
|
||||
// compiling. Such an nmethod doesn't begin with a NOP but with an ADRP.
|
||||
if (! (CalculateClassFingerprint && UseAOT && is_adrp_at(verified_entry))) {
|
||||
assert(nativeInstruction_at(verified_entry)->is_jump_or_nop()
|
||||
|| nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(),
|
||||
"Aarch64 cannot replace non-jump with jump");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Patch this nmethod atomically.
|
||||
if (Assembler::reachable_from_branch_at(verified_entry, dest)) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2014, 2108, Red Hat Inc. 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
|
||||
@ -95,6 +95,8 @@ class NativeInstruction {
|
||||
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
|
||||
@ -148,6 +150,46 @@ inline NativeInstruction* nativeInstruction_at(uint32_t *address) {
|
||||
return (NativeInstruction*)address;
|
||||
}
|
||||
|
||||
class NativePltCall: public NativeInstruction {
|
||||
public:
|
||||
enum Arm_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 &
|
||||
@ -169,7 +211,7 @@ class NativeCall: public NativeInstruction {
|
||||
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");
|
||||
@ -191,6 +233,12 @@ class NativeCall: public NativeInstruction {
|
||||
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);
|
||||
|
||||
@ -381,6 +429,39 @@ class NativeLoadAddress: public NativeInstruction {
|
||||
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 {
|
||||
@ -441,6 +522,31 @@ inline NativeGeneralJump* nativeGeneralJump_at(address address) {
|
||||
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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Red Hat Inc. 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
|
||||
@ -560,7 +560,7 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
|
||||
__ 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;
|
||||
@ -2278,7 +2278,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// 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
|
||||
@ -2360,7 +2360,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
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())));
|
||||
@ -2486,7 +2486,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
__ reset_last_Java_frame(false);
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (EnableJVMCI) {
|
||||
if (EnableJVMCI || UseAOT) {
|
||||
__ bind(after_fetch_unroll_info_call);
|
||||
}
|
||||
#endif
|
||||
@ -2644,7 +2644,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
_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);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Red Hat Inc. 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
|
||||
@ -484,7 +484,7 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
|
||||
#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);
|
||||
|
@ -382,6 +382,10 @@ class CodeBuffer: public StackObj {
|
||||
|
||||
address _last_insn; // used to merge consecutive memory barriers, loads or stores.
|
||||
|
||||
#if INCLUDE_AOT
|
||||
bool _immutable_PIC;
|
||||
#endif
|
||||
|
||||
address _decode_begin; // start address for decode
|
||||
address decode_begin();
|
||||
|
||||
@ -396,6 +400,9 @@ class CodeBuffer: public StackObj {
|
||||
_overflow_arena = NULL;
|
||||
_code_strings = CodeStrings();
|
||||
_last_insn = NULL;
|
||||
#if INCLUDE_AOT
|
||||
_immutable_PIC = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void initialize(address code_start, csize_t code_size) {
|
||||
@ -629,6 +636,13 @@ class CodeBuffer: public StackObj {
|
||||
// Log a little info about section usage in the CodeBuffer
|
||||
void log_section_sizes(const char* name);
|
||||
|
||||
#if INCLUDE_AOT
|
||||
// True if this is a code buffer used for immutable PIC, i.e. AOT
|
||||
// compilation.
|
||||
bool immutable_PIC() { return _immutable_PIC; }
|
||||
void set_immutable_PIC(bool pic) { _immutable_PIC = pic; }
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
public:
|
||||
// Printing / Decoding
|
||||
|
@ -591,6 +591,9 @@ JVMCIEnv::CodeInstallResult CodeInstaller::gather_metadata(Handle target, Handle
|
||||
// Get instructions and constants CodeSections early because we need it.
|
||||
_instructions = buffer.insts();
|
||||
_constants = buffer.consts();
|
||||
#if INCLUDE_AOT
|
||||
buffer.set_immutable_PIC(_immutable_pic_compilation);
|
||||
#endif
|
||||
|
||||
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
|
||||
JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, false, CHECK_OK);
|
||||
@ -624,6 +627,9 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand
|
||||
// Get instructions and constants CodeSections early because we need it.
|
||||
_instructions = buffer.insts();
|
||||
_constants = buffer.consts();
|
||||
#if INCLUDE_AOT
|
||||
buffer.set_immutable_PIC(_immutable_pic_compilation);
|
||||
#endif
|
||||
|
||||
initialize_fields(target(), JNIHandles::resolve(compiled_code_obj), CHECK_OK);
|
||||
JVMCIEnv::CodeInstallResult result = initialize_buffer(buffer, true, CHECK_OK);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -528,7 +528,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
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":
|
||||
@ -576,7 +576,7 @@ public final class BinaryContainer implements SymbolTable {
|
||||
* @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() +
|
||||
// "]");
|
||||
|
134
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java
Normal file
134
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AArch64JELFRelocObject.java
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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_<ARCH>_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;
|
||||
}
|
||||
}
|
127
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java
Normal file
127
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/AMD64JELFRelocObject.java
Normal file
@ -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_<ARCH>_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;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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
|
||||
@ -208,12 +209,26 @@ final class Elf {
|
||||
/**
|
||||
* 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 +255,20 @@ final class Elf {
|
||||
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);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -55,6 +55,8 @@ final class ElfTargetInfo {
|
||||
|
||||
if (archStr.equals("amd64") || archStr.equals("x86_64")) {
|
||||
arch = Elf64_Ehdr.EM_X86_64;
|
||||
} else if (archStr.equals("aarch64")) {
|
||||
arch = Elf64_Ehdr.EM_AARCH64;
|
||||
} else {
|
||||
System.out.println("Unsupported architecture " + archStr);
|
||||
arch = Elf64_Ehdr.EM_NONE;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -46,7 +46,7 @@ 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 JELFRelocObject {
|
||||
public abstract class JELFRelocObject {
|
||||
|
||||
private final BinaryContainer binContainer;
|
||||
|
||||
@ -54,12 +54,22 @@ public class JELFRelocObject {
|
||||
|
||||
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<ElfSection> sections,
|
||||
String sectName,
|
||||
byte[] scnData,
|
||||
@ -295,75 +305,6 @@ public class JELFRelocObject {
|
||||
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_<ARCH>_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<ElfSection> sections,
|
||||
ElfRelocTable elfRelocTable,
|
||||
int symtabsectidx) {
|
||||
@ -383,4 +324,7 @@ public class JELFRelocObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable);
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -32,6 +32,8 @@ import jdk.tools.jaotc.StubInformation;
|
||||
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 @@ final class CodeSectionProcessor {
|
||||
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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -39,6 +39,8 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
|
||||
|
||||
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,17 @@ final class CompiledMethodInfo {
|
||||
|
||||
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")) {
|
||||
// The mark is at the end of a group of three instructions:
|
||||
// adrp; add; ldr
|
||||
adjOffset += 12;
|
||||
} else {
|
||||
// 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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -25,8 +25,10 @@ package jdk.tools.jaotc;
|
||||
|
||||
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;
|
||||
|
||||
@ -36,6 +38,8 @@ public interface ELFMacroAssembler {
|
||||
Architecture architecture = target.arch;
|
||||
if (architecture instanceof AMD64) {
|
||||
return new AMD64ELFMacroAssembler(target);
|
||||
} else if (architecture instanceof AArch64) {
|
||||
return new AArch64ELFMacroAssembler(target);
|
||||
} else {
|
||||
throw new InternalError("Unsupported architecture " + architecture);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -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 @@ public abstract class InstructionDecoder {
|
||||
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);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -38,7 +38,19 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||
|
||||
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 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||
*/
|
||||
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();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -69,6 +69,7 @@ final class Linker {
|
||||
if (name.endsWith(".so")) {
|
||||
objectFileName = name.substring(0, name.length() - ".so".length());
|
||||
}
|
||||
objectFileName = objectFileName + ".o";
|
||||
linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
|
||||
linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
|
||||
linkerCheck = linkerPath + " -v";
|
||||
@ -130,7 +131,8 @@ final class Linker {
|
||||
throw new InternalError(errorMessage);
|
||||
}
|
||||
File objFile = new File(objectFileName);
|
||||
if (objFile.exists()) {
|
||||
boolean keepObjFile = Boolean.parseBoolean(System.getProperty("aot.keep.objFile", "false"));
|
||||
if (objFile.exists() && !keepObjFile) {
|
||||
if (!objFile.delete()) {
|
||||
throw new InternalError("Failed to delete " + objectFileName + " file");
|
||||
}
|
||||
|
129
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java
Normal file
129
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64ELFMacroAssembler.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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);
|
||||
}
|
||||
}
|
47
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java
Normal file
47
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/aarch64/AArch64InstructionDecoder.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 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
|
||||
@ -44,6 +44,7 @@ module jdk.internal.vm.compiler {
|
||||
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;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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
|
||||
@ -26,6 +27,7 @@ import static jdk.vm.ci.aarch64.AArch64.cpuRegisters;
|
||||
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;
|
||||
@ -1347,15 +1349,13 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
/**
|
||||
* 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.
|
||||
@ -1371,6 +1371,10 @@ public abstract class AArch64Assembler extends Assembler {
|
||||
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);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, Red Hat Inc. 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
|
||||
@ -1564,6 +1565,12 @@ public class AArch64MacroAssembler extends AArch64Assembler {
|
||||
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.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user