src/cpu/aarch64/vm/nativeInst_aarch64.hpp
Print this page
@@ -51,10 +51,11 @@
// The base class for different kinds of native instruction abstractions.
// Provides the primitive operations to manipulate code relative to this.
class NativeInstruction VALUE_OBJ_CLASS_SPEC {
friend class Relocation;
+ friend bool is_NativeCallTrampolineStub_at(address);
public:
enum { instruction_size = 4 };
inline bool is_nop();
bool is_dtrace_trap();
inline bool is_illegal();
@@ -64,27 +65,30 @@
inline bool is_cond_jump();
bool is_safepoint_poll();
inline bool is_mov_literal64();
bool is_movz();
bool is_movk();
+ bool is_sigill_zombie_not_entrant();
protected:
address addr_at(int offset) const { return address(this) + offset; }
s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); }
u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); }
jint int_at(int offset) const { return *(jint*) addr_at(offset); }
+ juint uint_at(int offset) const { return *(juint*) addr_at(offset); }
- intptr_t ptr_at(int offset) const { return *(intptr_t*) addr_at(offset); }
+ address ptr_at(int offset) const { return *(address*) addr_at(offset); }
oop oop_at (int offset) const { return *(oop*) addr_at(offset); }
void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; }
void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; }
- void set_ptr_at (int offset, intptr_t ptr) { *(intptr_t*) addr_at(offset) = ptr; }
+ void set_uint_at(int offset, jint i) { *(juint*)addr_at(offset) = i; }
+ 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; }
public:
// unit test stuff
@@ -128,34 +132,21 @@
address next_instruction_address() const { return addr_at(return_address_offset); }
int displacement() const { return (int_at(displacement_offset) << 6) >> 4; }
address displacement_address() const { return addr_at(displacement_offset); }
address return_address() const { return addr_at(return_address_offset); }
address destination() const;
+
void set_destination(address dest) {
int offset = dest - instruction_address();
unsigned int insn = 0b100101 << 26;
assert((offset & 3) == 0, "should be");
offset >>= 2;
offset &= (1 << 26) - 1; // mask off insn part
insn |= offset;
set_int_at(displacement_offset, insn);
- ICache::invalidate_range(instruction_address(), instruction_size);
}
- // Similar to replace_mt_safe, but just changes the destination. The
- // important thing is that free-running threads are able to execute
- // this call instruction at all times. If the call is an immediate BL
- // instruction we can simply rely on atomicity of 32-bit writes to
- // make sure other threads will see no intermediate states.
-
- // We cannot rely on locks here, since the free-running threads must run at
- // full speed.
- //
- // Used in the runtime linkage of calls; see class CompiledIC.
- // (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.)
- void set_destination_mt_safe(address dest) { set_destination(dest); }
-
void verify_alignment() { ; }
void verify();
void print();
// Creation
@@ -173,10 +164,27 @@
// MT-safe patching of a call instruction.
static void insert(address code_pos, address entry);
static void replace_mt_safe(address instr_addr, address code_buffer);
+
+ // Similar to replace_mt_safe, but just changes the destination. The
+ // important thing is that free-running threads are able to execute
+ // this call instruction at all times. If the call is an immediate BL
+ // instruction we can simply rely on atomicity of 32-bit writes to
+ // make sure other threads will see no intermediate states.
+
+ // We cannot rely on locks here, since the free-running threads must run at
+ // full speed.
+ //
+ // Used in the runtime linkage of calls; see class CompiledIC.
+ // (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.)
+
+ // The parameter assert_lock disables the assertion during code generation.
+ void set_destination_mt_safe(address dest, bool assert_lock = true);
+
+ address get_trampoline();
};
inline NativeCall* nativeCall_at(address address) {
NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
#ifdef ASSERT
@@ -376,14 +384,14 @@
}
class NativeGeneralJump: public NativeJump {
public:
enum AArch64_specific_constants {
- instruction_size = 4,
+ instruction_size = 4 * 4,
instruction_offset = 0,
data_offset = 0,
- next_instruction_offset = 4
+ next_instruction_offset = 4 * 4
};
static void insert_unconditional(address code_pos, address entry);
static void replace_mt_safe(address instr_addr, address code_buffer);
static void verify();
};
@@ -448,6 +456,36 @@
inline bool NativeInstruction::is_jump_or_nop() {
return is_nop() || is_jump();
}
+// Call trampoline stubs.
+class NativeCallTrampolineStub : public NativeInstruction {
+ public:
+
+ enum AArch64_specific_constants {
+ instruction_size = 4 * 4,
+ instruction_offset = 0,
+ data_offset = 2 * 4,
+ next_instruction_offset = 4 * 4
+ };
+
+ address destination(nmethod *nm = NULL) const;
+ void set_destination(address new_destination);
+ ptrdiff_t destination_offset() const;
+};
+
+inline bool is_NativeCallTrampolineStub_at(address addr) {
+ // Ensure that the stub is exactly
+ // ldr xscratch1, L
+ // br xscratch1
+ // L:
+ uint32_t *i = (uint32_t *)addr;
+ return i[0] == 0x58000048 && i[1] == 0xd61f0100;
+}
+
+inline NativeCallTrampolineStub* nativeCallTrampolineStub_at(address addr) {
+ assert(is_NativeCallTrampolineStub_at(addr), "no call trampoline found");
+ return (NativeCallTrampolineStub*)addr;
+}
+
#endif // CPU_AARCH64_VM_NATIVEINST_AARCH64_HPP