8166562: C2: Suppress relocations in scratch emit

Reviewed-by: kvn
This commit is contained in:
Goetz Lindenmaier 2016-09-22 18:33:47 +02:00
parent 3c1ab21ffa
commit 969358fbb3
5 changed files with 79 additions and 73 deletions

View file

@ -1097,21 +1097,19 @@ EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address en
// No entry point given, use the current pc. // No entry point given, use the current pc.
if (entry_point == NULL) entry_point = __ pc(); if (entry_point == NULL) entry_point = __ pc();
if (!Compile::current()->in_scratch_emit_size()) { // Put the entry point as a constant into the constant pool.
// Put the entry point as a constant into the constant pool. const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none);
const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none); if (entry_point_toc_addr == NULL) {
if (entry_point_toc_addr == NULL) { ciEnv::current()->record_out_of_memory_failure();
ciEnv::current()->record_out_of_memory_failure(); return offsets;
return offsets;
}
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
if (ciEnv::current()->failing()) { return offsets; } // Code cache may be full.
__ relocate(rtype);
} }
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset);
if (ciEnv::current()->failing()) { return offsets; } // Code cache may be full.
__ relocate(rtype);
// Note: At this point we do not have the address of the trampoline // Note: At this point we do not have the address of the trampoline
// stub, and the entry point might be too far away for bl, so __ pc() // stub, and the entry point might be too far away for bl, so __ pc()
// serves as dummy and the bl will be patched later. // serves as dummy and the bl will be patched later.
@ -2434,23 +2432,21 @@ encode %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int toc_offset = 0; int toc_offset = 0;
if (!ra_->C->in_scratch_emit_size()) { address const_toc_addr;
address const_toc_addr; // Create a non-oop constant, no relocation needed.
// Create a non-oop constant, no relocation needed. // If it is an IC, it has a virtual_call_Relocation.
// If it is an IC, it has a virtual_call_Relocation. const_toc_addr = __ long_constant((jlong)$src$$constant);
const_toc_addr = __ long_constant((jlong)$src$$constant); if (const_toc_addr == NULL) {
if (const_toc_addr == NULL) { ciEnv::current()->record_out_of_memory_failure();
ciEnv::current()->record_out_of_memory_failure(); return;
return;
}
// Get the constant's TOC offset.
toc_offset = __ offset_to_method_toc(const_toc_addr);
// Keep the current instruction offset in mind.
((loadConLNode*)this)->_cbuf_insts_offset = __ offset();
} }
// Get the constant's TOC offset.
toc_offset = __ offset_to_method_toc(const_toc_addr);
// Keep the current instruction offset in mind.
((loadConLNode*)this)->_cbuf_insts_offset = __ offset();
__ ld($dst$$Register, toc_offset, $toc$$Register); __ ld($dst$$Register, toc_offset, $toc$$Register);
%} %}
@ -2586,32 +2582,30 @@ encode %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int toc_offset = 0; int toc_offset = 0;
if (!ra_->C->in_scratch_emit_size()) { intptr_t val = $src$$constant;
intptr_t val = $src$$constant; relocInfo::relocType constant_reloc = $src->constant_reloc(); // src
relocInfo::relocType constant_reloc = $src->constant_reloc(); // src address const_toc_addr;
address const_toc_addr; if (constant_reloc == relocInfo::oop_type) {
if (constant_reloc == relocInfo::oop_type) { // Create an oop constant and a corresponding relocation.
// Create an oop constant and a corresponding relocation. AddressLiteral a = __ allocate_oop_address((jobject)val);
AddressLiteral a = __ allocate_oop_address((jobject)val); const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); __ relocate(a.rspec());
__ relocate(a.rspec()); } else if (constant_reloc == relocInfo::metadata_type) {
} else if (constant_reloc == relocInfo::metadata_type) { AddressLiteral a = __ constant_metadata_address((Metadata *)val);
AddressLiteral a = __ constant_metadata_address((Metadata *)val); const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none); __ relocate(a.rspec());
__ relocate(a.rspec()); } else {
} else { // Create a non-oop constant, no relocation needed.
// Create a non-oop constant, no relocation needed. const_toc_addr = __ long_constant((jlong)$src$$constant);
const_toc_addr = __ long_constant((jlong)$src$$constant);
}
if (const_toc_addr == NULL) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
// Get the constant's TOC offset.
toc_offset = __ offset_to_method_toc(const_toc_addr);
} }
if (const_toc_addr == NULL) {
ciEnv::current()->record_out_of_memory_failure();
return;
}
// Get the constant's TOC offset.
toc_offset = __ offset_to_method_toc(const_toc_addr);
__ ld($dst$$Register, toc_offset, $toc$$Register); __ ld($dst$$Register, toc_offset, $toc$$Register);
%} %}
@ -3282,28 +3276,26 @@ encode %{
} else { } else {
// Remember the offset not the address. // Remember the offset not the address.
const int start_offset = __ offset(); const int start_offset = __ offset();
// The trampoline stub. // The trampoline stub.
if (!Compile::current()->in_scratch_emit_size()) { // No entry point given, use the current pc.
// No entry point given, use the current pc. // Make sure branch fits into
// Make sure branch fits into if (entry_point == 0) entry_point = __ pc();
if (entry_point == 0) entry_point = __ pc();
// Put the entry point as a constant into the constant pool. // Put the entry point as a constant into the constant pool.
const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none); const address entry_point_toc_addr = __ address_constant(entry_point, RelocationHolder::none);
if (entry_point_toc_addr == NULL) { if (entry_point_toc_addr == NULL) {
ciEnv::current()->record_out_of_memory_failure(); ciEnv::current()->record_out_of_memory_failure();
return; return;
}
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
if (ciEnv::current()->failing()) { return; } // Code cache may be full.
int method_index = resolved_method_index(cbuf);
__ relocate(_optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
: static_call_Relocation::spec(method_index));
} }
const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr);
// Emit the trampoline stub which will be related to the branch-and-link below.
CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset);
if (ciEnv::current()->failing()) { return; } // Code cache may be full.
int method_index = resolved_method_index(cbuf);
__ relocate(_optimized_virtual ? opt_virtual_call_Relocation::spec(method_index)
: static_call_Relocation::spec(method_index));
// The real call. // The real call.
// Note: At this point we do not have the address of the trampoline // Note: At this point we do not have the address of the trampoline

View file

@ -153,6 +153,8 @@ void AbstractAssembler::generate_stack_overflow_check(int frame_size_in_bytes) {
void Label::add_patch_at(CodeBuffer* cb, int branch_loc) { void Label::add_patch_at(CodeBuffer* cb, int branch_loc) {
assert(_loc == -1, "Label is unbound"); assert(_loc == -1, "Label is unbound");
// Don't add patch locations during scratch emit.
if (cb->insts()->scratch_emit()) { return; }
if (_patch_index < PatchCacheSize) { if (_patch_index < PatchCacheSize) {
_patches[_patch_index] = branch_loc; _patches[_patch_index] = branch_loc;
} else { } else {

View file

@ -331,6 +331,8 @@ void CodeSection::relocate(address at, relocInfo::relocType rtype, int format, j
} }
void CodeSection::relocate(address at, RelocationHolder const& spec, int format) { void CodeSection::relocate(address at, RelocationHolder const& spec, int format) {
// Do not relocate in scratch buffers.
if (scratch_emit()) { return; }
Relocation* reloc = spec.reloc(); Relocation* reloc = spec.reloc();
relocInfo::relocType rtype = (relocInfo::relocType) reloc->type(); relocInfo::relocType rtype = (relocInfo::relocType) reloc->type();
if (rtype == relocInfo::none) return; if (rtype == relocInfo::none) return;

View file

@ -92,6 +92,7 @@ class CodeSection VALUE_OBJ_CLASS_SPEC {
address _locs_point; // last relocated position (grows upward) address _locs_point; // last relocated position (grows upward)
bool _locs_own; // did I allocate the locs myself? bool _locs_own; // did I allocate the locs myself?
bool _frozen; // no more expansion of this section bool _frozen; // no more expansion of this section
bool _scratch_emit; // Buffer is used for scratch emit, don't relocate.
char _index; // my section number (SECT_INST, etc.) char _index; // my section number (SECT_INST, etc.)
CodeBuffer* _outer; // enclosing CodeBuffer CodeBuffer* _outer; // enclosing CodeBuffer
@ -108,6 +109,7 @@ class CodeSection VALUE_OBJ_CLASS_SPEC {
_locs_point = NULL; _locs_point = NULL;
_locs_own = false; _locs_own = false;
_frozen = false; _frozen = false;
_scratch_emit = false;
debug_only(_index = (char)-1); debug_only(_index = (char)-1);
debug_only(_outer = (CodeBuffer*)badAddress); debug_only(_outer = (CodeBuffer*)badAddress);
} }
@ -166,6 +168,10 @@ class CodeSection VALUE_OBJ_CLASS_SPEC {
bool is_frozen() const { return _frozen; } bool is_frozen() const { return _frozen; }
bool has_locs() const { return _locs_end != NULL; } bool has_locs() const { return _locs_end != NULL; }
// Mark scratch buffer.
void set_scratch_emit() { _scratch_emit = true; }
bool scratch_emit() { return _scratch_emit; }
CodeBuffer* outer() const { return _outer; } CodeBuffer* outer() const { return _outer; }
// is a given address in this section? (2nd version is end-inclusive) // is a given address in this section? (2nd version is end-inclusive)

View file

@ -574,6 +574,10 @@ uint Compile::scratch_emit_size(const Node* n) {
buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize); buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize);
buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], lsize); buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], lsize);
buf.stubs()->initialize_shared_locs( &locs_buf[lsize * 2], lsize); buf.stubs()->initialize_shared_locs( &locs_buf[lsize * 2], lsize);
// Mark as scratch buffer.
buf.consts()->set_scratch_emit();
buf.insts()->set_scratch_emit();
buf.stubs()->set_scratch_emit();
// Do the emission. // Do the emission.