mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +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.
|
// anywhere in the codeCache then we are always reachable.
|
||||||
// This would have to change if we ever save/restore shared code
|
// This would have to change if we ever save/restore shared code
|
||||||
// to be more pessimistic.
|
// to be more pessimistic.
|
||||||
|
|
||||||
disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
|
disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
|
||||||
if (!is_simm32(disp)) return false;
|
if (!is_simm32(disp)) return false;
|
||||||
disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int));
|
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);
|
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,
|
void Assembler::emit_data64(jlong data,
|
||||||
relocInfo::relocType rtype,
|
relocInfo::relocType rtype,
|
||||||
int format) {
|
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
|
#ifndef SERIALGC
|
||||||
|
|
||||||
|
@ -7121,17 +7133,6 @@ void MacroAssembler::subptr(Register dst, Register src) {
|
||||||
LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, 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
|
// C++ bool manipulation
|
||||||
void MacroAssembler::testbool(Register dst) {
|
void MacroAssembler::testbool(Register dst) {
|
||||||
if(sizeof(bool) == 1)
|
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, relocInfo::relocType rtype, int format = 0);
|
||||||
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
|
void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
|
||||||
|
|
||||||
|
|
||||||
bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
|
bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
|
||||||
|
|
||||||
// These are all easily abused and hence protected
|
// These are all easily abused and hence protected
|
||||||
|
@ -683,6 +682,8 @@ private:
|
||||||
static bool is_simm32(int32_t x) { return true; }
|
static bool is_simm32(int32_t x) { return true; }
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
|
|
||||||
|
static bool is_polling_page_far() NOT_LP64({ return false;});
|
||||||
|
|
||||||
// Generic instructions
|
// Generic instructions
|
||||||
// Does 32bit or 64bit as needed for the platform. In some sense these
|
// 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
|
// 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 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, 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)); }
|
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()),
|
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
|
||||||
relocInfo::poll_return_type);
|
relocInfo::poll_return_type);
|
||||||
|
|
||||||
// NOTE: the requires that the polling page be reachable else the reloc
|
if (Assembler::is_polling_page_far()) {
|
||||||
// goes to the movq that loads the address and not the faulting instruction
|
__ lea(rscratch1, polling_page);
|
||||||
// which breaks the signal handler code
|
__ relocate(relocInfo::poll_return_type);
|
||||||
|
__ testl(rax, Address(rscratch1, 0));
|
||||||
__ test32(rax, polling_page);
|
} else {
|
||||||
|
__ testl(rax, polling_page);
|
||||||
|
}
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,20 +662,17 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||||
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
|
AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
|
||||||
relocInfo::poll_type);
|
relocInfo::poll_type);
|
||||||
|
guarantee(info != NULL, "Shouldn't be NULL");
|
||||||
if (info != NULL) {
|
|
||||||
add_debug_info_for_branch(info);
|
|
||||||
} else {
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
|
|
||||||
int offset = __ offset();
|
int offset = __ offset();
|
||||||
|
if (Assembler::is_polling_page_far()) {
|
||||||
// NOTE: the requires that the polling page be reachable else the reloc
|
__ lea(rscratch1, polling_page);
|
||||||
// goes to the movq that loads the address and not the faulting instruction
|
offset = __ offset();
|
||||||
// which breaks the signal handler code
|
add_debug_info_for_branch(info);
|
||||||
|
__ testl(rax, Address(rscratch1, 0));
|
||||||
__ test32(rax, polling_page);
|
} else {
|
||||||
|
add_debug_info_for_branch(info);
|
||||||
|
__ testl(rax, polling_page);
|
||||||
|
}
|
||||||
return offset;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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 {
|
class NativeTstRegMem: public NativeInstruction {
|
||||||
public:
|
public:
|
||||||
enum Intel_specific_constants {
|
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,13 +537,26 @@ inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) =
|
||||||
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
|
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
|
||||||
inline bool NativeInstruction::is_safepoint_poll() {
|
inline bool NativeInstruction::is_safepoint_poll() {
|
||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
if ( ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
|
if (Assembler::is_polling_page_far()) {
|
||||||
ubyte_at(1) == 0x05 ) { // 00 rax 101
|
// 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 {
|
||||||
|
if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
|
||||||
|
ubyte_at(1) == 0x05) { // 00 rax 101
|
||||||
address fault = addr_at(6) + int_at(2);
|
address fault = addr_at(6) + int_at(2);
|
||||||
return os::is_poll_address(fault);
|
return os::is_poll_address(fault);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
|
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
|
||||||
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
|
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -198,6 +198,7 @@ void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen)
|
||||||
|
|
||||||
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
|
if (!Assembler::is_polling_page_far()) {
|
||||||
typedef Assembler::WhichOperand WhichOperand;
|
typedef Assembler::WhichOperand WhichOperand;
|
||||||
WhichOperand which = (WhichOperand) format();
|
WhichOperand which = (WhichOperand) format();
|
||||||
// This format is imm but it is really disp32
|
// This format is imm but it is really disp32
|
||||||
|
@ -213,12 +214,13 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffe
|
||||||
|
|
||||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||||
* disp = (int32_t)new_disp;
|
* disp = (int32_t)new_disp;
|
||||||
|
}
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
|
if (!Assembler::is_polling_page_far()) {
|
||||||
typedef Assembler::WhichOperand WhichOperand;
|
typedef Assembler::WhichOperand WhichOperand;
|
||||||
WhichOperand which = (WhichOperand) format();
|
WhichOperand which = (WhichOperand) format();
|
||||||
// This format is imm but it is really disp32
|
// This format is imm but it is really disp32
|
||||||
|
@ -234,5 +236,6 @@ void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, Co
|
||||||
|
|
||||||
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
|
||||||
* disp = (int32_t)new_disp;
|
* disp = (int32_t)new_disp;
|
||||||
|
}
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
}
|
}
|
||||||
|
|
|
@ -574,12 +574,11 @@ int MachCallDynamicJavaNode::ret_addr_offset()
|
||||||
// In os_cpu .ad file
|
// In os_cpu .ad file
|
||||||
// int MachCallRuntimeNode::ret_addr_offset()
|
// int MachCallRuntimeNode::ret_addr_offset()
|
||||||
|
|
||||||
// Indicate if the safepoint node needs the polling page as an input.
|
// Indicate if the safepoint node needs the polling page as an input,
|
||||||
// Since amd64 does not have absolute addressing but RIP-relative
|
// it does if the polling page is more than disp32 away.
|
||||||
// addressing and the polling page is within 2G, it doesn't.
|
|
||||||
bool SafePointNode::needs_polling_address_input()
|
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;
|
framesize -= 2*wordSize;
|
||||||
|
|
||||||
if (framesize) {
|
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("\t");
|
||||||
}
|
}
|
||||||
|
|
||||||
st->print_cr("popq\trbp");
|
st->print_cr("popq rbp");
|
||||||
if (do_polling() && C->is_method_compilation()) {
|
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");
|
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
|
#endif
|
||||||
|
@ -1033,45 +1038,22 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
|
||||||
emit_opcode(cbuf, 0x58 | RBP_enc);
|
emit_opcode(cbuf, 0x58 | RBP_enc);
|
||||||
|
|
||||||
if (do_polling() && C->is_method_compilation()) {
|
if (do_polling() && C->is_method_compilation()) {
|
||||||
// testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
|
MacroAssembler _masm(&cbuf);
|
||||||
// XXX reg_mem doesn't support RIP-relative addressing yet
|
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
|
||||||
cbuf.set_insts_mark();
|
if (Assembler::is_polling_page_far()) {
|
||||||
cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_return_type, 0); // XXX
|
__ lea(rscratch1, polling_page);
|
||||||
emit_opcode(cbuf, 0x85); // testl
|
__ relocate(relocInfo::poll_return_type);
|
||||||
emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
|
__ testl(rax, Address(rscratch1, 0));
|
||||||
// cbuf.insts_mark() is beginning of instruction
|
} else {
|
||||||
emit_d32_reloc(cbuf, os::get_polling_page());
|
__ testl(rax, polling_page);
|
||||||
// relocInfo::poll_return_type,
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
|
uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
|
||||||
{
|
{
|
||||||
Compile* C = ra_->C;
|
return MachNode::size(ra_); // too many variables; just compute it
|
||||||
int framesize = C->frame_slots() << LogBytesPerInt;
|
// the hard way
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MachEpilogNode::reloc() const
|
int MachEpilogNode::reloc() const
|
||||||
|
@ -3914,22 +3896,6 @@ encode %{
|
||||||
|
|
||||||
// done:
|
// 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);
|
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
|
// Pointer Immediate
|
||||||
operand immN() %{
|
operand immN() %{
|
||||||
match(ConN);
|
match(ConN);
|
||||||
|
@ -6568,6 +6543,16 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
|
||||||
ins_pipe(ialu_reg);
|
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)
|
instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
match(Set dst src);
|
match(Set dst src);
|
||||||
|
@ -12473,14 +12458,33 @@ instruct cmpFastUnlock(rFlagsReg cr,
|
||||||
// Safepoint Instructions
|
// Safepoint Instructions
|
||||||
instruct safePoint_poll(rFlagsReg cr)
|
instruct safePoint_poll(rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(!Assembler::is_polling_page_far());
|
||||||
match(SafePoint);
|
match(SafePoint);
|
||||||
effect(KILL cr);
|
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" %}
|
"# Safepoint: poll for GC" %}
|
||||||
size(6); // Opcode + ModRM + Disp32 == 6 bytes
|
|
||||||
ins_cost(125);
|
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);
|
ins_pipe(ialu_reg_mem);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue