mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6964776: c2 should ensure the polling page is reachable on 64 bit
Materialize the pointer to the polling page in a register instead of using rip-relative addressing when the distance from the code cache is larger than disp32. Reviewed-by: never, kvn
This commit is contained in:
parent
5387ee459e
commit
36303f61b6
6 changed files with 204 additions and 177 deletions
|
@ -3510,7 +3510,6 @@ bool Assembler::reachable(AddressLiteral adr) {
|
|||
// anywhere in the codeCache then we are always reachable.
|
||||
// This would have to change if we ever save/restore shared code
|
||||
// to be more pessimistic.
|
||||
|
||||
disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
|
||||
if (!is_simm32(disp)) return false;
|
||||
disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int));
|
||||
|
@ -3534,6 +3533,14 @@ bool Assembler::reachable(AddressLiteral adr) {
|
|||
return is_simm32(disp);
|
||||
}
|
||||
|
||||
// Check if the polling page is not reachable from the code cache using rip-relative
|
||||
// addressing.
|
||||
bool Assembler::is_polling_page_far() {
|
||||
intptr_t addr = (intptr_t)os::get_polling_page();
|
||||
return !is_simm32(addr - (intptr_t)CodeCache::low_bound()) ||
|
||||
!is_simm32(addr - (intptr_t)CodeCache::high_bound());
|
||||
}
|
||||
|
||||
void Assembler::emit_data64(jlong data,
|
||||
relocInfo::relocType rtype,
|
||||
int format) {
|
||||
|
@ -6886,6 +6893,11 @@ void MacroAssembler::sign_extend_short(Register reg) {
|
|||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::testl(Register dst, AddressLiteral src) {
|
||||
assert(reachable(src), "Address should be reachable");
|
||||
testl(dst, as_Address(src));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef SERIALGC
|
||||
|
||||
|
@ -7121,17 +7133,6 @@ void MacroAssembler::subptr(Register dst, Register src) {
|
|||
LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src));
|
||||
}
|
||||
|
||||
void MacroAssembler::test32(Register src1, AddressLiteral src2) {
|
||||
// src2 must be rval
|
||||
|
||||
if (reachable(src2)) {
|
||||
testl(src1, as_Address(src2));
|
||||
} else {
|
||||
lea(rscratch1, src2);
|
||||
testl(src1, Address(rscratch1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// C++ bool manipulation
|
||||
void MacroAssembler::testbool(Register dst) {
|
||||
if(sizeof(bool) == 1)
|
||||
|
|
|
@ -580,7 +580,6 @@ private:
|
|||
void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
|
||||
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
|
||||
|
||||
|
||||
bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
|
||||
|
||||
// These are all easily abused and hence protected
|
||||
|
@ -683,6 +682,8 @@ private:
|
|||
static bool is_simm32(int32_t x) { return true; }
|
||||
#endif // _LP64
|
||||
|
||||
static bool is_polling_page_far() NOT_LP64({ return false;});
|
||||
|
||||
// Generic instructions
|
||||
// Does 32bit or 64bit as needed for the platform. In some sense these
|
||||
// belong in macro assembler but there is no need for both varieties to exist
|
||||
|
@ -2094,7 +2095,10 @@ class MacroAssembler: public Assembler {
|
|||
|
||||
void leal32(Register dst, Address src) { leal(dst, src); }
|
||||
|
||||
void test32(Register src1, AddressLiteral src2);
|
||||
// Import other testl() methods from the parent class or else
|
||||
// they will be hidden by the following overriding declaration.
|
||||
using Assembler::testl;
|
||||
void testl(Register dst, AddressLiteral src);
|
||||
|
||||
void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
|
||||
void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
|
||||
|
|
|
@ -648,12 +648,13 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
|||
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
|
||||
relocInfo::poll_return_type);
|
||||
|
||||
// NOTE: the requires that the polling page be reachable else the reloc
|
||||
// goes to the movq that loads the address and not the faulting instruction
|
||||
// which breaks the signal handler code
|
||||
|
||||
__ test32(rax, polling_page);
|
||||
|
||||
if (Assembler::is_polling_page_far()) {
|
||||
__ lea(rscratch1, polling_page);
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
__ testl(rax, Address(rscratch1, 0));
|
||||
} else {
|
||||
__ testl(rax, polling_page);
|
||||
}
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
|
@ -661,20 +662,17 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
|||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
|
||||
relocInfo::poll_type);
|
||||
|
||||
if (info != NULL) {
|
||||
add_debug_info_for_branch(info);
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
guarantee(info != NULL, "Shouldn't be NULL");
|
||||
int offset = __ offset();
|
||||
|
||||
// NOTE: the requires that the polling page be reachable else the reloc
|
||||
// goes to the movq that loads the address and not the faulting instruction
|
||||
// which breaks the signal handler code
|
||||
|
||||
__ test32(rax, polling_page);
|
||||
if (Assembler::is_polling_page_far()) {
|
||||
__ lea(rscratch1, polling_page);
|
||||
offset = __ offset();
|
||||
add_debug_info_for_branch(info);
|
||||
__ testl(rax, Address(rscratch1, 0));
|
||||
} else {
|
||||
add_debug_info_for_branch(info);
|
||||
__ testl(rax, polling_page);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2011, 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
|
||||
|
@ -519,7 +519,11 @@ class NativeReturnX: public NativeInstruction {
|
|||
class NativeTstRegMem: public NativeInstruction {
|
||||
public:
|
||||
enum Intel_specific_constants {
|
||||
instruction_code_memXregl = 0x85
|
||||
instruction_rex_prefix_mask = 0xF0,
|
||||
instruction_rex_prefix = Assembler::REX,
|
||||
instruction_code_memXregl = 0x85,
|
||||
modrm_mask = 0x38, // select reg from the ModRM byte
|
||||
modrm_reg = 0x00 // rax
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -533,12 +537,25 @@ inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) =
|
|||
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
|
||||
inline bool NativeInstruction::is_safepoint_poll() {
|
||||
#ifdef AMD64
|
||||
if ( ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
|
||||
ubyte_at(1) == 0x05 ) { // 00 rax 101
|
||||
address fault = addr_at(6) + int_at(2);
|
||||
return os::is_poll_address(fault);
|
||||
if (Assembler::is_polling_page_far()) {
|
||||
// two cases, depending on the choice of the base register in the address.
|
||||
if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
|
||||
ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
|
||||
(ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
|
||||
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
|
||||
(ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
|
||||
ubyte_at(1) == 0x05) { // 00 rax 101
|
||||
address fault = addr_at(6) + int_at(2);
|
||||
return os::is_poll_address(fault);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2011, 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
|
||||
|
@ -198,41 +198,44 @@ void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen)
|
|||
|
||||
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
||||
#ifdef _LP64
|
||||
typedef Assembler::WhichOperand WhichOperand;
|
||||
WhichOperand which = (WhichOperand) format();
|
||||
// This format is imm but it is really disp32
|
||||
which = Assembler::disp32_operand;
|
||||
address orig_addr = old_addr_for(addr(), src, dest);
|
||||
NativeInstruction* oni = nativeInstruction_at(orig_addr);
|
||||
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
|
||||
// This poll_addr is incorrect by the size of the instruction it is irrelevant
|
||||
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
|
||||
if (!Assembler::is_polling_page_far()) {
|
||||
typedef Assembler::WhichOperand WhichOperand;
|
||||
WhichOperand which = (WhichOperand) format();
|
||||
// This format is imm but it is really disp32
|
||||
which = Assembler::disp32_operand;
|
||||
address orig_addr = old_addr_for(addr(), src, dest);
|
||||
NativeInstruction* oni = nativeInstruction_at(orig_addr);
|
||||
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
|
||||
// This poll_addr is incorrect by the size of the instruction it is irrelevant
|
||||
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
|
||||
|
||||
NativeInstruction* ni = nativeInstruction_at(addr());
|
||||
intptr_t new_disp = poll_addr - (intptr_t) ni;
|
||||
|
||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||
* disp = (int32_t)new_disp;
|
||||
NativeInstruction* ni = nativeInstruction_at(addr());
|
||||
intptr_t new_disp = poll_addr - (intptr_t) ni;
|
||||
|
||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||
* disp = (int32_t)new_disp;
|
||||
}
|
||||
#endif // _LP64
|
||||
}
|
||||
|
||||
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
||||
#ifdef _LP64
|
||||
typedef Assembler::WhichOperand WhichOperand;
|
||||
WhichOperand which = (WhichOperand) format();
|
||||
// This format is imm but it is really disp32
|
||||
which = Assembler::disp32_operand;
|
||||
address orig_addr = old_addr_for(addr(), src, dest);
|
||||
NativeInstruction* oni = nativeInstruction_at(orig_addr);
|
||||
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
|
||||
// This poll_addr is incorrect by the size of the instruction it is irrelevant
|
||||
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
|
||||
if (!Assembler::is_polling_page_far()) {
|
||||
typedef Assembler::WhichOperand WhichOperand;
|
||||
WhichOperand which = (WhichOperand) format();
|
||||
// This format is imm but it is really disp32
|
||||
which = Assembler::disp32_operand;
|
||||
address orig_addr = old_addr_for(addr(), src, dest);
|
||||
NativeInstruction* oni = nativeInstruction_at(orig_addr);
|
||||
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
|
||||
// This poll_addr is incorrect by the size of the instruction it is irrelevant
|
||||
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
|
||||
|
||||
NativeInstruction* ni = nativeInstruction_at(addr());
|
||||
intptr_t new_disp = poll_addr - (intptr_t) ni;
|
||||
NativeInstruction* ni = nativeInstruction_at(addr());
|
||||
intptr_t new_disp = poll_addr - (intptr_t) ni;
|
||||
|
||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||
* disp = (int32_t)new_disp;
|
||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||
* disp = (int32_t)new_disp;
|
||||
}
|
||||
#endif // _LP64
|
||||
}
|
||||
|
|
|
@ -574,12 +574,11 @@ int MachCallDynamicJavaNode::ret_addr_offset()
|
|||
// In os_cpu .ad file
|
||||
// int MachCallRuntimeNode::ret_addr_offset()
|
||||
|
||||
// Indicate if the safepoint node needs the polling page as an input.
|
||||
// Since amd64 does not have absolute addressing but RIP-relative
|
||||
// addressing and the polling page is within 2G, it doesn't.
|
||||
// Indicate if the safepoint node needs the polling page as an input,
|
||||
// it does if the polling page is more than disp32 away.
|
||||
bool SafePointNode::needs_polling_address_input()
|
||||
{
|
||||
return false;
|
||||
return Assembler::is_polling_page_far();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -992,15 +991,21 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
|
|||
framesize -= 2*wordSize;
|
||||
|
||||
if (framesize) {
|
||||
st->print_cr("addq\trsp, %d\t# Destroy frame", framesize);
|
||||
st->print_cr("addq rsp, %d\t# Destroy frame", framesize);
|
||||
st->print("\t");
|
||||
}
|
||||
|
||||
st->print_cr("popq\trbp");
|
||||
st->print_cr("popq rbp");
|
||||
if (do_polling() && C->is_method_compilation()) {
|
||||
st->print_cr("\ttestl\trax, [rip + #offset_to_poll_page]\t"
|
||||
"# Safepoint: poll for GC");
|
||||
st->print("\t");
|
||||
if (Assembler::is_polling_page_far()) {
|
||||
st->print_cr("movq rscratch1, #polling_page_address\n\t"
|
||||
"testl rax, [rscratch1]\t"
|
||||
"# Safepoint: poll for GC");
|
||||
} else {
|
||||
st->print_cr("testl rax, [rip + #offset_to_poll_page]\t"
|
||||
"# Safepoint: poll for GC");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1033,45 +1038,22 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
|
|||
emit_opcode(cbuf, 0x58 | RBP_enc);
|
||||
|
||||
if (do_polling() && C->is_method_compilation()) {
|
||||
// testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
|
||||
// XXX reg_mem doesn't support RIP-relative addressing yet
|
||||
cbuf.set_insts_mark();
|
||||
cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_return_type, 0); // XXX
|
||||
emit_opcode(cbuf, 0x85); // testl
|
||||
emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
|
||||
// cbuf.insts_mark() is beginning of instruction
|
||||
emit_d32_reloc(cbuf, os::get_polling_page());
|
||||
// relocInfo::poll_return_type,
|
||||
MacroAssembler _masm(&cbuf);
|
||||
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
|
||||
if (Assembler::is_polling_page_far()) {
|
||||
__ lea(rscratch1, polling_page);
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
__ testl(rax, Address(rscratch1, 0));
|
||||
} else {
|
||||
__ testl(rax, polling_page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
|
||||
{
|
||||
Compile* C = ra_->C;
|
||||
int framesize = C->frame_slots() << LogBytesPerInt;
|
||||
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
|
||||
// Remove word for return adr already pushed
|
||||
// and RBP
|
||||
framesize -= 2*wordSize;
|
||||
|
||||
uint size = 0;
|
||||
|
||||
if (do_polling() && C->is_method_compilation()) {
|
||||
size += 6;
|
||||
}
|
||||
|
||||
// count popq rbp
|
||||
size++;
|
||||
|
||||
if (framesize) {
|
||||
if (framesize < 0x80) {
|
||||
size += 4;
|
||||
} else if (framesize) {
|
||||
size += 7;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
return MachNode::size(ra_); // too many variables; just compute it
|
||||
// the hard way
|
||||
}
|
||||
|
||||
int MachEpilogNode::reloc() const
|
||||
|
@ -3410,8 +3392,8 @@ encode %{
|
|||
}
|
||||
if (EmitSync & 1) {
|
||||
// Without cast to int32_t a movptr will destroy r10 which is typically obj
|
||||
masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
|
||||
masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
|
||||
masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
|
||||
masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
|
||||
} else
|
||||
if (EmitSync & 2) {
|
||||
Label DONE_LABEL;
|
||||
|
@ -3439,10 +3421,10 @@ encode %{
|
|||
} else {
|
||||
Label DONE_LABEL, IsInflated, Egress;
|
||||
|
||||
masm.movptr(tmpReg, Address(objReg, 0)) ;
|
||||
masm.movptr(tmpReg, Address(objReg, 0)) ;
|
||||
masm.testl (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased
|
||||
masm.jcc (Assembler::notZero, IsInflated) ;
|
||||
|
||||
masm.jcc (Assembler::notZero, IsInflated) ;
|
||||
|
||||
// it's stack-locked, biased or neutral
|
||||
// TODO: optimize markword triage order to reduce the number of
|
||||
// conditional branches in the most common cases.
|
||||
|
@ -3456,9 +3438,9 @@ encode %{
|
|||
}
|
||||
|
||||
// was q will it destroy high?
|
||||
masm.orl (tmpReg, 1) ;
|
||||
masm.movptr(Address(boxReg, 0), tmpReg) ;
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
masm.orl (tmpReg, 1) ;
|
||||
masm.movptr(Address(boxReg, 0), tmpReg) ;
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
|
||||
if (_counters != NULL) {
|
||||
masm.cond_inc32(Assembler::equal,
|
||||
|
@ -3485,16 +3467,16 @@ encode %{
|
|||
// fetched _owner. If the CAS is successful we may
|
||||
// avoid an RTO->RTS upgrade on the $line.
|
||||
// Without cast to int32_t a movptr will destroy r10 which is typically obj
|
||||
masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
|
||||
masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
|
||||
|
||||
masm.mov (boxReg, tmpReg) ;
|
||||
masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
masm.testptr(tmpReg, tmpReg) ;
|
||||
masm.jcc (Assembler::notZero, DONE_LABEL) ;
|
||||
masm.mov (boxReg, tmpReg) ;
|
||||
masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
masm.testptr(tmpReg, tmpReg) ;
|
||||
masm.jcc (Assembler::notZero, DONE_LABEL) ;
|
||||
|
||||
// It's inflated and appears unlocked
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
// Intentional fall-through into DONE_LABEL ...
|
||||
|
||||
masm.bind (DONE_LABEL) ;
|
||||
|
@ -3513,8 +3495,8 @@ encode %{
|
|||
Register tmpReg = as_Register($tmp$$reg);
|
||||
MacroAssembler masm(&cbuf);
|
||||
|
||||
if (EmitSync & 4) {
|
||||
masm.cmpptr(rsp, 0) ;
|
||||
if (EmitSync & 4) {
|
||||
masm.cmpptr(rsp, 0) ;
|
||||
} else
|
||||
if (EmitSync & 8) {
|
||||
Label DONE_LABEL;
|
||||
|
@ -3541,25 +3523,25 @@ encode %{
|
|||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
|
||||
}
|
||||
|
||||
masm.movptr(tmpReg, Address(objReg, 0)) ;
|
||||
masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
|
||||
masm.jcc (Assembler::zero, DONE_LABEL) ;
|
||||
masm.testl (tmpReg, 0x02) ;
|
||||
masm.jcc (Assembler::zero, Stacked) ;
|
||||
|
||||
|
||||
masm.movptr(tmpReg, Address(objReg, 0)) ;
|
||||
masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
|
||||
masm.jcc (Assembler::zero, DONE_LABEL) ;
|
||||
masm.testl (tmpReg, 0x02) ;
|
||||
masm.jcc (Assembler::zero, Stacked) ;
|
||||
|
||||
// It's inflated
|
||||
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
masm.xorptr(boxReg, r15_thread) ;
|
||||
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
|
||||
masm.jcc (Assembler::notZero, DONE_LABEL) ;
|
||||
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
|
||||
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
|
||||
masm.jcc (Assembler::notZero, CheckSucc) ;
|
||||
masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
|
||||
masm.jmp (DONE_LABEL) ;
|
||||
|
||||
if ((EmitSync & 65536) == 0) {
|
||||
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
masm.xorptr(boxReg, r15_thread) ;
|
||||
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
|
||||
masm.jcc (Assembler::notZero, DONE_LABEL) ;
|
||||
masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
|
||||
masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
|
||||
masm.jcc (Assembler::notZero, CheckSucc) ;
|
||||
masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
|
||||
masm.jmp (DONE_LABEL) ;
|
||||
|
||||
if ((EmitSync & 65536) == 0) {
|
||||
Label LSuccess, LGoSlowPath ;
|
||||
masm.bind (CheckSucc) ;
|
||||
masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
|
||||
|
@ -3591,9 +3573,9 @@ encode %{
|
|||
masm.jmp (DONE_LABEL) ;
|
||||
}
|
||||
|
||||
masm.bind (Stacked) ;
|
||||
masm.bind (Stacked) ;
|
||||
masm.movptr(tmpReg, Address (boxReg, 0)) ; // re-fetch
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
if (os::is_MP()) { masm.lock(); }
|
||||
masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box
|
||||
|
||||
if (EmitSync & 65536) {
|
||||
|
@ -3914,22 +3896,6 @@ encode %{
|
|||
|
||||
// done:
|
||||
%}
|
||||
|
||||
// Safepoint Poll. This polls the safepoint page, and causes an
|
||||
// exception if it is not readable. Unfortunately, it kills
|
||||
// RFLAGS in the process.
|
||||
enc_class enc_safepoint_poll
|
||||
%{
|
||||
// testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
|
||||
// XXX reg_mem doesn't support RIP-relative addressing yet
|
||||
cbuf.set_insts_mark();
|
||||
cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_type, 0); // XXX
|
||||
emit_opcode(cbuf, 0x85); // testl
|
||||
emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
|
||||
// cbuf.insts_mark() is beginning of instruction
|
||||
emit_d32_reloc(cbuf, os::get_polling_page());
|
||||
// relocInfo::poll_type,
|
||||
%}
|
||||
%}
|
||||
|
||||
|
||||
|
@ -4233,6 +4199,15 @@ operand immP0()
|
|||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immP_poll() %{
|
||||
predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
|
||||
match(ConP);
|
||||
|
||||
// formats are generated automatically for constants and base registers
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Pointer Immediate
|
||||
operand immN() %{
|
||||
match(ConN);
|
||||
|
@ -4840,7 +4815,7 @@ operand regF()
|
|||
%}
|
||||
|
||||
// Double register operands
|
||||
operand regD()
|
||||
operand regD()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(double_reg));
|
||||
match(RegD);
|
||||
|
@ -6568,6 +6543,16 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
|
|||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct loadConP_poll(rRegP dst, immP_poll src) %{
|
||||
match(Set dst src);
|
||||
format %{ "movq $dst, $src\t!ptr" %}
|
||||
ins_encode %{
|
||||
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
|
||||
__ lea($dst$$Register, polling_page);
|
||||
%}
|
||||
ins_pipe(ialu_reg_fat);
|
||||
%}
|
||||
|
||||
instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst src);
|
||||
|
@ -7241,11 +7226,11 @@ instruct bytes_reverse_long(rRegL dst) %{
|
|||
instruct bytes_reverse_unsigned_short(rRegI dst) %{
|
||||
match(Set dst (ReverseBytesUS dst));
|
||||
|
||||
format %{ "bswapl $dst\n\t"
|
||||
format %{ "bswapl $dst\n\t"
|
||||
"shrl $dst,16\n\t" %}
|
||||
ins_encode %{
|
||||
__ bswapl($dst$$Register);
|
||||
__ shrl($dst$$Register, 16);
|
||||
__ shrl($dst$$Register, 16);
|
||||
%}
|
||||
ins_pipe( ialu_reg );
|
||||
%}
|
||||
|
@ -7253,11 +7238,11 @@ instruct bytes_reverse_unsigned_short(rRegI dst) %{
|
|||
instruct bytes_reverse_short(rRegI dst) %{
|
||||
match(Set dst (ReverseBytesS dst));
|
||||
|
||||
format %{ "bswapl $dst\n\t"
|
||||
format %{ "bswapl $dst\n\t"
|
||||
"sar $dst,16\n\t" %}
|
||||
ins_encode %{
|
||||
__ bswapl($dst$$Register);
|
||||
__ sarl($dst$$Register, 16);
|
||||
__ sarl($dst$$Register, 16);
|
||||
%}
|
||||
ins_pipe( ialu_reg );
|
||||
%}
|
||||
|
@ -7480,7 +7465,7 @@ instruct membar_volatile(rFlagsReg cr) %{
|
|||
effect(KILL cr);
|
||||
ins_cost(400);
|
||||
|
||||
format %{
|
||||
format %{
|
||||
$$template
|
||||
if (os::is_MP()) {
|
||||
$$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
|
||||
|
@ -8291,7 +8276,7 @@ instruct storePConditional(memory heap_top_ptr,
|
|||
rFlagsReg cr)
|
||||
%{
|
||||
match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
|
||||
|
||||
|
||||
format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
|
||||
"If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
|
||||
opcode(0x0F, 0xB1);
|
||||
|
@ -9854,9 +9839,9 @@ instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
|||
|
||||
// Xor Register with Immediate -1
|
||||
instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{
|
||||
match(Set dst (XorI dst imm));
|
||||
match(Set dst (XorI dst imm));
|
||||
|
||||
format %{ "not $dst" %}
|
||||
format %{ "not $dst" %}
|
||||
ins_encode %{
|
||||
__ notl($dst$$Register);
|
||||
%}
|
||||
|
@ -10097,9 +10082,9 @@ instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
|||
|
||||
// Xor Register with Immediate -1
|
||||
instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{
|
||||
match(Set dst (XorL dst imm));
|
||||
match(Set dst (XorL dst imm));
|
||||
|
||||
format %{ "notq $dst" %}
|
||||
format %{ "notq $dst" %}
|
||||
ins_encode %{
|
||||
__ notq($dst$$Register);
|
||||
%}
|
||||
|
@ -12473,14 +12458,33 @@ instruct cmpFastUnlock(rFlagsReg cr,
|
|||
// Safepoint Instructions
|
||||
instruct safePoint_poll(rFlagsReg cr)
|
||||
%{
|
||||
predicate(!Assembler::is_polling_page_far());
|
||||
match(SafePoint);
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "testl rax, [rip + #offset_to_poll_page]\t"
|
||||
format %{ "testl rax, [rip + #offset_to_poll_page]\t"
|
||||
"# Safepoint: poll for GC" %}
|
||||
size(6); // Opcode + ModRM + Disp32 == 6 bytes
|
||||
ins_cost(125);
|
||||
ins_encode(enc_safepoint_poll);
|
||||
ins_encode %{
|
||||
AddressLiteral addr(os::get_polling_page(), relocInfo::poll_type);
|
||||
__ testl(rax, addr);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct safePoint_poll_far(rFlagsReg cr, rRegP poll)
|
||||
%{
|
||||
predicate(Assembler::is_polling_page_far());
|
||||
match(SafePoint poll);
|
||||
effect(KILL cr, USE poll);
|
||||
|
||||
format %{ "testl rax, [$poll]\t"
|
||||
"# Safepoint: poll for GC" %}
|
||||
ins_cost(125);
|
||||
ins_encode %{
|
||||
__ relocate(relocInfo::poll_type);
|
||||
__ testl(rax, Address($poll$$Register, 0));
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue