提交 7fef4161 编写于 作者: I iveresov

6964776: c2 should ensure the polling page is reachable on 64 bit

Summary: 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
上级 fdf76f6c
......@@ -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) {
guarantee(info != NULL, "Shouldn't be NULL");
int offset = __ offset();
if (Assembler::is_polling_page_far()) {
__ lea(rscratch1, polling_page);
offset = __ offset();
add_debug_info_for_branch(info);
__ testl(rax, Address(rscratch1, 0));
} else {
ShouldNotReachHere();
add_debug_info_for_branch(info);
__ testl(rax, polling_page);
}
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);
return offset;
}
......
/*
* 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 ||
......
/*
* 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;
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;
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;
}
#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;
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;
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;
}
#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" %}
ins_cost(125);
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" %}
size(6); // Opcode + ModRM + Disp32 == 6 bytes
ins_cost(125);
ins_encode(enc_safepoint_poll);
ins_encode %{
__ relocate(relocInfo::poll_type);
__ testl(rax, Address($poll$$Register, 0));
%}
ins_pipe(ialu_reg_mem);
%}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册