8240363: Refactor Compile::Output() to its own Phase

Reviewed-by: kvn, vlivanov
This commit is contained in:
Erik Österlund 2020-03-16 12:27:42 +00:00
parent 6ddb0f2b2c
commit 21cd75cb98
28 changed files with 1388 additions and 1228 deletions

View file

@ -1575,7 +1575,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset return 0; // absolute addressing, no offset
} }
@ -1602,9 +1602,9 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
Compile* C = ra_->C; Compile* C = ra_->C;
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->output()->frame_slots() << LogBytesPerInt;
if (C->need_stack_bang(framesize)) if (C->output()->need_stack_bang(framesize))
st->print("# stack bang size=%d\n\t", framesize); st->print("# stack bang size=%d\n\t", framesize);
if (framesize < ((1 << 9) + 2 * wordSize)) { if (framesize < ((1 << 9) + 2 * wordSize)) {
@ -1625,7 +1625,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
// n.b. frame size includes space for return pc and rfp // n.b. frame size includes space for return pc and rfp
const long framesize = C->frame_size_in_bytes(); const long framesize = C->output()->frame_size_in_bytes();
assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment");
// insert a nop at the start of the prolog so we can patch in a // insert a nop at the start of the prolog so we can patch in a
@ -1643,8 +1643,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ bind(L_skip_barrier); __ bind(L_skip_barrier);
} }
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
if (C->need_stack_bang(bangsize) && UseStackBanging) if (C->output()->need_stack_bang(bangsize) && UseStackBanging)
__ generate_stack_overflow_check(bangsize); __ generate_stack_overflow_check(bangsize);
__ build_frame(framesize); __ build_frame(framesize);
@ -1653,12 +1653,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Unimplemented(); Unimplemented();
} }
C->set_frame_complete(cbuf.insts_size()); C->output()->set_frame_complete(cbuf.insts_size());
if (C->has_mach_constant_base_node()) { if (C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -1679,7 +1679,7 @@ int MachPrologNode::reloc() const
#ifndef PRODUCT #ifndef PRODUCT
void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
Compile* C = ra_->C; Compile* C = ra_->C;
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->output()->frame_slots() << LogBytesPerInt;
st->print("# pop frame %d\n\t",framesize); st->print("# pop frame %d\n\t",framesize);
@ -1705,7 +1705,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = C->frame_slots() << LogBytesPerInt; int framesize = C->output()->frame_slots() << LogBytesPerInt;
__ remove_frame(framesize); __ remove_frame(framesize);

View file

@ -56,6 +56,7 @@
#include "opto/compile.hpp" #include "opto/compile.hpp"
#include "opto/intrinsicnode.hpp" #include "opto/intrinsicnode.hpp"
#include "opto/node.hpp" #include "opto/node.hpp"
#include "opto/output.hpp"
#endif #endif
#ifdef PRODUCT #ifdef PRODUCT
@ -745,7 +746,7 @@ address MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
CompileTask* task = ciEnv::current()->task(); CompileTask* task = ciEnv::current()->task();
in_scratch_emit_size = in_scratch_emit_size =
(task != NULL && is_c2_compile(task->comp_level()) && (task != NULL && is_c2_compile(task->comp_level()) &&
Compile::current()->in_scratch_emit_size()); Compile::current()->output()->in_scratch_emit_size());
#endif #endif
if (!in_scratch_emit_size) { if (!in_scratch_emit_size) {
address stub = emit_trampoline_stub(offset(), entry.target()); address stub = emit_trampoline_stub(offset(), entry.target());

View file

@ -194,7 +194,7 @@ void emit_hi(CodeBuffer &cbuf, int val) { }
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
int offset = -(size() / 2); int offset = -(size() / 2);
// flds, fldd: 8-bit offset multiplied by 4: +/- 1024 // flds, fldd: 8-bit offset multiplied by 4: +/- 1024
// ldr, ldrb : 12-bit offset: +/- 4096 // ldr, ldrb : 12-bit offset: +/- 4096
@ -211,7 +211,7 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, Phase
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
Register r = as_Register(ra_->get_encode(this)); Register r = as_Register(ra_->get_encode(this));
@ -245,9 +245,9 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("NOP"); st->print("\t"); st->print_cr("NOP"); st->print("\t");
} }
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;
bangsize -= 2*wordSize; bangsize -= 2*wordSize;
@ -257,7 +257,7 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
// some VM calls (such as call site linkage) can use several kilobytes of // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
} }
st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t"); st->print_cr("PUSH R_FP|R_LR_LR"); st->print("\t");
@ -275,9 +275,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ nop(); __ nop();
} }
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
// Remove two words for return addr and fp, // Remove two words for return addr and fp,
framesize -= 2*wordSize; framesize -= 2*wordSize;
bangsize -= 2*wordSize; bangsize -= 2*wordSize;
@ -287,7 +287,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// some VM calls (such as call site linkage) can use several kilobytes of // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
__ arm_stack_overflow_check(bangsize, Rtemp); __ arm_stack_overflow_check(bangsize, Rtemp);
} }
@ -298,13 +298,13 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// offset from scratch buffer is not valid // offset from scratch buffer is not valid
if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) { if (strcmp(cbuf.name(), "Compile::Fill_buffer") == 0) {
C->set_frame_complete( __ offset() ); C->output()->set_frame_complete( __ offset() );
} }
if (C->has_mach_constant_base_node()) { if (C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -322,7 +322,7 @@ int MachPrologNode::reloc() const {
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
Compile* C = ra_->C; Compile* C = ra_->C;
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
framesize -= 2*wordSize; framesize -= 2*wordSize;
if (framesize != 0) { if (framesize != 0) {
@ -342,7 +342,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
Compile* C = ra_->C; Compile* C = ra_->C;
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
framesize -= 2*wordSize; framesize -= 2*wordSize;
if (framesize != 0) { if (framesize != 0) {
__ add_slow(SP, SP, framesize); __ add_slow(SP, SP, framesize);
@ -827,7 +827,7 @@ void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
uint BoxLockNode::size(PhaseRegAlloc *ra_) const { uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
// BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
assert(ra_ == ra_->C->regalloc(), "sanity"); assert(ra_ == ra_->C->regalloc(), "sanity");
return ra_->C->scratch_emit_size(this); return ra_->C->output()->scratch_emit_size(this);
} }
//============================================================================= //=============================================================================

View file

@ -1297,7 +1297,7 @@ static inline jlong replicate_immF(float con) {
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = BITS64_CONSTANT_TABLE_BASE_mask(); const RegMask& MachConstantBaseNode::_out_RegMask = BITS64_CONSTANT_TABLE_BASE_mask();
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset return 0; // absolute addressing, no offset
} }
@ -1338,10 +1338,10 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
#ifndef PRODUCT #ifndef PRODUCT
void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
Compile* C = ra_->C; Compile* C = ra_->C;
const long framesize = C->frame_slots() << LogBytesPerInt; const long framesize = C->output()->frame_slots() << LogBytesPerInt;
st->print("PROLOG\n\t"); st->print("PROLOG\n\t");
if (C->need_stack_bang(framesize)) { if (C->output()->need_stack_bang(framesize)) {
st->print("stack_overflow_check\n\t"); st->print("stack_overflow_check\n\t");
} }
@ -1381,7 +1381,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
const long framesize = C->frame_size_in_bytes(); const long framesize = C->output()->frame_size_in_bytes();
assert(framesize % (2 * wordSize) == 0, "must preserve 2*wordSize alignment"); assert(framesize % (2 * wordSize) == 0, "must preserve 2*wordSize alignment");
const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/; const bool method_is_frameless = false /* TODO: PPC port C->is_frameless_method()*/;
@ -1426,9 +1426,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// use several kilobytes of stack. But the stack safety zone should // use several kilobytes of stack. But the stack safety zone should
// account for that. See bugs 4446381, 4468289, 4497237. // account for that. See bugs 4446381, 4468289, 4497237.
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
assert(bangsize >= framesize || bangsize <= 0, "stack bang size incorrect"); assert(bangsize >= framesize || bangsize <= 0, "stack bang size incorrect");
if (C->need_stack_bang(bangsize) && UseStackBanging) { if (C->output()->need_stack_bang(bangsize) && UseStackBanging) {
// Unfortunately we cannot use the function provided in // Unfortunately we cannot use the function provided in
// assembler.cpp as we have to emulate the pipes. So I had to // assembler.cpp as we have to emulate the pipes. So I had to
// insert the code of generate_stack_overflow_check(), see // insert the code of generate_stack_overflow_check(), see
@ -1482,7 +1482,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
bang_offset += page_size; bang_offset += page_size;
} }
// R11 trashed // R11 trashed
} // C->need_stack_bang(framesize) && UseStackBanging } // C->output()->need_stack_bang(framesize) && UseStackBanging
unsigned int bytes = (unsigned int)framesize; unsigned int bytes = (unsigned int)framesize;
long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes); long offset = Assembler::align_addr(bytes, frame::alignment_in_bytes);
@ -1537,7 +1537,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
___(std) std(return_pc, _abi(lr), callers_sp); ___(std) std(return_pc, _abi(lr), callers_sp);
} }
C->set_frame_complete(cbuf.insts_size()); C->output()->set_frame_complete(cbuf.insts_size());
} }
#undef ___ #undef ___
#undef ___stop #undef ___stop
@ -1573,7 +1573,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
const long framesize = ((long)C->frame_slots()) << LogBytesPerInt; const long framesize = ((long)C->output()->frame_slots()) << LogBytesPerInt;
assert(framesize >= 0, "negative frame-size?"); assert(framesize >= 0, "negative frame-size?");
const bool method_needs_polling = do_polling() && C->is_method_compilation(); const bool method_needs_polling = do_polling() && C->is_method_compilation();
@ -2786,7 +2786,7 @@ encode %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
if (!ra_->C->in_scratch_emit_size()) { if (!ra_->C->output()->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.
@ -3053,7 +3053,7 @@ encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_addis); // TODO: PPC port $archOpcode(ppc64Opcode_addis);
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
if (!ra_->C->in_scratch_emit_size()) { if (!ra_->C->output()->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;
@ -3791,7 +3791,7 @@ encode %{
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
if (!ra_->C->in_scratch_emit_size()) { if (!ra_->C->output()->in_scratch_emit_size()) {
// Create a call trampoline stub for the given method. // Create a call trampoline stub for the given method.
const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method; const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method;
const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none); const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none);
@ -6285,7 +6285,7 @@ instruct loadConL_lo(iRegLdst dst, immL src, iRegLdst base) %{
size(4); size(4);
ins_encode %{ ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_ld); // TODO: PPC port $archOpcode(ppc64Opcode_ld);
int offset = ra_->C->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; int offset = ra_->C->output()->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset;
__ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register);
%} %}
ins_pipe(pipe_class_memory); ins_pipe(pipe_class_memory);
@ -6570,7 +6570,7 @@ instruct loadConP_lo(iRegPdst dst, immP_NM src, iRegLdst base) %{
size(4); size(4);
ins_encode %{ ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_ld); // TODO: PPC port $archOpcode(ppc64Opcode_ld);
int offset = ra_->C->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset; int offset = ra_->C->output()->in_scratch_emit_size() ? 0 : _const_toc_offset_hi_node->_const_toc_offset;
__ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register); __ ld($dst$$Register, MacroAssembler::largeoffset_si16_si16_lo(offset), $base$$Register);
%} %}
ins_pipe(pipe_class_memory); ins_pipe(pipe_class_memory);

View file

@ -54,7 +54,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// That's why we must use the macroassembler to generate a stub. // That's why we must use the macroassembler to generate a stub.
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
address stub = __ start_a_stub(Compile::MAX_stubs_size); address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
if (stub == NULL) { if (stub == NULL) {
return NULL; // CodeBuffer::expand failed. return NULL; // CodeBuffer::expand failed.
} }

View file

@ -795,7 +795,7 @@ static int emit_call_reloc(MacroAssembler &_masm, intptr_t entry_point, Relocati
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = _Z_PTR_REG_mask; const RegMask& MachConstantBaseNode::_out_RegMask = _Z_PTR_REG_mask;
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset return 0; // absolute addressing, no offset
} }
@ -840,15 +840,15 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
st->print("\t"); st->print("\t");
} }
long framesize = C->frame_size_in_bytes(); long framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
// Calls to C2R adapters often do not accept exceptional returns. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be // We require that their callers must bang for them. But be
// careful, because some VM calls (such as call site linkage) can // careful, because some VM calls (such as call site linkage) can
// use several kilobytes of stack. But the stack safety zone should // use several kilobytes of stack. But the stack safety zone should
// account for that. See bugs 4446381, 4468289, 4497237. // account for that. See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize) && UseStackBanging) { if (C->output()->need_stack_bang(bangsize) && UseStackBanging) {
st->print_cr("# stack bang"); st->print("\t"); st->print_cr("# stack bang"); st->print("\t");
} }
st->print_cr("push_frame %d", (int)-framesize); st->print_cr("push_frame %d", (int)-framesize);
@ -862,8 +862,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ verify_thread(); __ verify_thread();
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
size_t bangsize = C->bang_size_in_bytes(); size_t bangsize = C->output()->bang_size_in_bytes();
assert(framesize % wordSize == 0, "must preserve wordSize alignment"); assert(framesize % wordSize == 0, "must preserve wordSize alignment");
@ -889,7 +889,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// careful, because some VM calls (such as call site linkage) can // careful, because some VM calls (such as call site linkage) can
// use several kilobytes of stack. But the stack safety zone should // use several kilobytes of stack. But the stack safety zone should
// account for that. See bugs 4446381, 4468289, 4497237. // account for that. See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize) && UseStackBanging) { if (C->output()->need_stack_bang(bangsize) && UseStackBanging) {
__ generate_stack_overflow_check(bangsize); __ generate_stack_overflow_check(bangsize);
} }
@ -903,7 +903,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
if (C->has_mach_constant_base_node()) { if (C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -940,7 +940,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
bool need_polling = do_polling() && C->is_method_compilation(); bool need_polling = do_polling() && C->is_method_compilation();
// Pop frame, restore return_pc, and all stuff needed by interpreter. // Pop frame, restore return_pc, and all stuff needed by interpreter.
int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes); int frame_size_in_bytes = Assembler::align((C->output()->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes);
__ pop_frame_restore_retPC(frame_size_in_bytes); __ pop_frame_restore_retPC(frame_size_in_bytes);
if (StackReservedPages > 0 && C->has_reserved_stack_access()) { if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
@ -1257,7 +1257,7 @@ void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ra_) const {
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int rem_space = 0; int rem_space = 0;
if (!(ra_->C->in_scratch_emit_size())) { if (!(ra_->C->output()->in_scratch_emit_size())) {
rem_space = cbuf.insts()->remaining(); rem_space = cbuf.insts()->remaining();
if (rem_space <= _count*2 + 8) { if (rem_space <= _count*2 + 8) {
tty->print("NopNode: _count = %3.3d, remaining space before = %d", _count, rem_space); tty->print("NopNode: _count = %3.3d, remaining space before = %d", _count, rem_space);
@ -1268,7 +1268,7 @@ void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ra_) const {
__ z_nop(); __ z_nop();
} }
if (!(ra_->C->in_scratch_emit_size())) { if (!(ra_->C->output()->in_scratch_emit_size())) {
if (rem_space <= _count*2 + 8) { if (rem_space <= _count*2 + 8) {
int rem_space2 = cbuf.insts()->remaining(); int rem_space2 = cbuf.insts()->remaining();
tty->print_cr(", after = %d", rem_space2); tty->print_cr(", after = %d", rem_space2);

View file

@ -1002,7 +1002,7 @@ void emit_hi(CodeBuffer &cbuf, int val) { }
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask(); const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask();
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
if (UseRDPCForConstantTableBase) { if (UseRDPCForConstantTableBase) {
// The table base offset might be less but then it fits into // The table base offset might be less but then it fits into
// simm13 anyway and we are good (cf. MachConstantBaseNode::emit). // simm13 anyway and we are good (cf. MachConstantBaseNode::emit).
@ -1023,7 +1023,7 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, Phase
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
Register r = as_Register(ra_->get_encode(this)); Register r = as_Register(ra_->get_encode(this));
@ -1128,15 +1128,15 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("Verify_Thread"); st->print("\t"); st->print_cr("Verify_Thread"); st->print("\t");
} }
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
// Calls to C2R adapters often do not accept exceptional returns. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be careful, because // We require that their callers must bang for them. But be careful, because
// some VM calls (such as call site linkage) can use several kilobytes of // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t"); st->print_cr("! stack bang (%d bytes)", bangsize); st->print("\t");
} }
@ -1161,17 +1161,17 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ verify_thread(); __ verify_thread();
size_t framesize = C->frame_size_in_bytes(); size_t framesize = C->output()->frame_size_in_bytes();
assert(framesize >= 16*wordSize, "must have room for reg. save area"); assert(framesize >= 16*wordSize, "must have room for reg. save area");
assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment"); assert(framesize%(2*wordSize) == 0, "must preserve 2*wordSize alignment");
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
// Calls to C2R adapters often do not accept exceptional returns. // Calls to C2R adapters often do not accept exceptional returns.
// We require that their callers must bang for them. But be careful, because // We require that their callers must bang for them. But be careful, because
// some VM calls (such as call site linkage) can use several kilobytes of // some VM calls (such as call site linkage) can use several kilobytes of
// stack. But the stack safety zone should account for that. // stack. But the stack safety zone should account for that.
// See bugs 4446381, 4468289, 4497237. // See bugs 4446381, 4468289, 4497237.
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
__ generate_stack_overflow_check(bangsize); __ generate_stack_overflow_check(bangsize);
} }
@ -1182,12 +1182,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ add(G3, -framesize & 0x3ff, G3); __ add(G3, -framesize & 0x3ff, G3);
__ save(SP, G3, SP); __ save(SP, G3, SP);
} }
C->set_frame_complete( __ offset() ); C->output()->set_frame_complete( __ offset() );
if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) { if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -1570,7 +1570,7 @@ void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
uint BoxLockNode::size(PhaseRegAlloc *ra_) const { uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
// BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_) // BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
assert(ra_ == ra_->C->regalloc(), "sanity"); assert(ra_ == ra_->C->regalloc(), "sanity");
return ra_->C->scratch_emit_size(this); return ra_->C->output()->scratch_emit_size(this);
} }
//============================================================================= //=============================================================================
@ -2426,7 +2426,7 @@ encode %{
enc_class call_epilog %{ enc_class call_epilog %{
if( VerifyStackAtCalls ) { if( VerifyStackAtCalls ) {
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = ra_->C->frame_size_in_bytes(); int framesize = ra_->C->output()->frame_size_in_bytes();
Register temp_reg = G3; Register temp_reg = G3;
__ add(SP, framesize, temp_reg); __ add(SP, framesize, temp_reg);
__ cmp(temp_reg, FP); __ cmp(temp_reg, FP);
@ -8854,7 +8854,7 @@ instruct jumpXtnd(iRegX switch_val, o7RegI table) %{
// zero offsets because they might change when // zero offsets because they might change when
// MachConstantBaseNode decides to optimize the constant table // MachConstantBaseNode decides to optimize the constant table
// base. // base.
if ((constant_offset() == 0) && !Compile::current()->in_scratch_emit_size()) { if ((constant_offset() == 0) && !Compile::current()->output()->in_scratch_emit_size()) {
table_reg = $constanttablebase; table_reg = $constanttablebase;
} else { } else {
table_reg = O7; table_reg = O7;

View file

@ -29,6 +29,7 @@
#include "opto/compile.hpp" #include "opto/compile.hpp"
#include "opto/machnode.hpp" #include "opto/machnode.hpp"
#include "opto/node.hpp" #include "opto/node.hpp"
#include "opto/output.hpp"
#include "opto/regalloc.hpp" #include "opto/regalloc.hpp"
#include "utilities/align.hpp" #include "utilities/align.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
@ -126,7 +127,7 @@ IntelJccErratumAlignment::IntelJccErratumAlignment(MacroAssembler& masm, int jcc
return; return;
} }
if (Compile::current()->in_scratch_emit_size()) { if (Compile::current()->output()->in_scratch_emit_size()) {
// When we measure the size of this 32 byte alignment, we apply a conservative guess. // When we measure the size of this 32 byte alignment, we apply a conservative guess.
__ nop(jcc_size); __ nop(jcc_size);
} else if (IntelJccErratum::is_crossing_or_ending_at_32_byte_boundary(_start_pc, _start_pc + jcc_size)) { } else if (IntelJccErratum::is_crossing_or_ending_at_32_byte_boundary(_start_pc, _start_pc + jcc_size)) {
@ -141,7 +142,7 @@ IntelJccErratumAlignment::IntelJccErratumAlignment(MacroAssembler& masm, int jcc
IntelJccErratumAlignment::~IntelJccErratumAlignment() { IntelJccErratumAlignment::~IntelJccErratumAlignment() {
if (!VM_Version::has_intel_jcc_erratum() || if (!VM_Version::has_intel_jcc_erratum() ||
Compile::current()->in_scratch_emit_size()) { Compile::current()->output()->in_scratch_emit_size()) {
return; return;
} }

View file

@ -523,7 +523,7 @@ void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset return 0; // absolute addressing, no offset
} }
@ -552,13 +552,13 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
Compile* C = ra_->C; Compile* C = ra_->C;
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove wordSize for return addr which is already pushed. // Remove wordSize for return addr which is already pushed.
framesize -= wordSize; framesize -= wordSize;
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
framesize -= wordSize; framesize -= wordSize;
st->print("# stack bang (%d bytes)", bangsize); st->print("# stack bang (%d bytes)", bangsize);
st->print("\n\t"); st->print("\n\t");
@ -616,17 +616,17 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode(), C->stub_function() != NULL); __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, C->in_24_bit_fp_mode(), C->stub_function() != NULL);
C->set_frame_complete(cbuf.insts_size()); C->output()->set_frame_complete(cbuf.insts_size());
if (C->has_mach_constant_base_node()) { if (C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -643,7 +643,7 @@ int MachPrologNode::reloc() const {
#ifndef PRODUCT #ifndef PRODUCT
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
Compile *C = ra_->C; Compile *C = ra_->C;
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;
@ -682,7 +682,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
_masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); _masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
} }
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove two words for return addr and rbp, // Remove two words for return addr and rbp,
framesize -= 2*wordSize; framesize -= 2*wordSize;

View file

@ -785,7 +785,7 @@ void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
//============================================================================= //=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
int Compile::ConstantTable::calculate_table_base_offset() const { int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset return 0; // absolute addressing, no offset
} }
@ -814,13 +814,13 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
Compile* C = ra_->C; Compile* C = ra_->C;
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove wordSize for return addr which is already pushed. // Remove wordSize for return addr which is already pushed.
framesize -= wordSize; framesize -= wordSize;
if (C->need_stack_bang(bangsize)) { if (C->output()->need_stack_bang(bangsize)) {
framesize -= wordSize; framesize -= wordSize;
st->print("# stack bang (%d bytes)", bangsize); st->print("# stack bang (%d bytes)", bangsize);
st->print("\n\t"); st->print("\n\t");
@ -874,8 +874,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
Compile* C = ra_->C; Compile* C = ra_->C;
MacroAssembler _masm(&cbuf); MacroAssembler _masm(&cbuf);
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
int bangsize = C->bang_size_in_bytes(); int bangsize = C->output()->bang_size_in_bytes();
if (C->clinit_barrier_on_entry()) { if (C->clinit_barrier_on_entry()) {
assert(VM_Version::supports_fast_class_init_checks(), "sanity"); assert(VM_Version::supports_fast_class_init_checks(), "sanity");
@ -892,14 +892,14 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
__ bind(L_skip_barrier); __ bind(L_skip_barrier);
} }
__ verified_entry(framesize, C->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != NULL); __ verified_entry(framesize, C->output()->need_stack_bang(bangsize)?bangsize:0, false, C->stub_function() != NULL);
C->set_frame_complete(cbuf.insts_size()); C->output()->set_frame_complete(cbuf.insts_size());
if (C->has_mach_constant_base_node()) { if (C->has_mach_constant_base_node()) {
// NOTE: We set the table base offset here because users might be // NOTE: We set the table base offset here because users might be
// emitted before MachConstantBaseNode. // emitted before MachConstantBaseNode.
Compile::ConstantTable& constant_table = C->constant_table(); ConstantTable& constant_table = C->output()->constant_table();
constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
} }
} }
@ -925,7 +925,7 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
st->cr(); st->print("\t"); st->cr(); st->print("\t");
} }
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return adr already pushed // Remove word for return adr already pushed
// and RBP // and RBP
@ -966,7 +966,7 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
__ vzeroupper(); __ vzeroupper();
} }
int framesize = C->frame_size_in_bytes(); int framesize = C->output()->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return adr already pushed // Remove word for return adr already pushed
// and RBP // and RBP

View file

@ -3374,7 +3374,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
} }
// Start code line. // Start code line.
encoding->add_code(" _constant = C->constant_table().add"); encoding->add_code(" _constant = C->output()->constant_table().add");
// Parse everything in ( ) expression. // Parse everything in ( ) expression.
encoding->add_code("(this, "); encoding->add_code("(this, ");

View file

@ -237,6 +237,7 @@ int main(int argc, char *argv[])
AD.addInclude(AD._HPP_file, "memory/allocation.hpp"); AD.addInclude(AD._HPP_file, "memory/allocation.hpp");
AD.addInclude(AD._HPP_file, "oops/compressedOops.hpp"); AD.addInclude(AD._HPP_file, "oops/compressedOops.hpp");
AD.addInclude(AD._HPP_file, "code/nativeInst.hpp"); AD.addInclude(AD._HPP_file, "code/nativeInst.hpp");
AD.addInclude(AD._HPP_file, "opto/output.hpp");
AD.addInclude(AD._HPP_file, "opto/machnode.hpp"); AD.addInclude(AD._HPP_file, "opto/machnode.hpp");
AD.addInclude(AD._HPP_file, "opto/node.hpp"); AD.addInclude(AD._HPP_file, "opto/node.hpp");
AD.addInclude(AD._HPP_file, "opto/regalloc.hpp"); AD.addInclude(AD._HPP_file, "opto/regalloc.hpp");

View file

@ -2605,7 +2605,7 @@ void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
// For MachConstantNodes which are ideal jump nodes, fill the jump table. // For MachConstantNodes which are ideal jump nodes, fill the jump table.
if (inst.is_mach_constant() && inst.is_ideal_jump()) { if (inst.is_mach_constant() && inst.is_ideal_jump()) {
fprintf(fp, " ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n"); fprintf(fp, " ra_->C->output()->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
} }
// Output each operand's offset into the array of registers. // Output each operand's offset into the array of registers.
@ -2679,7 +2679,7 @@ void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
// For ideal jump nodes, add a jump-table entry. // For ideal jump nodes, add a jump-table entry.
if (inst.is_ideal_jump()) { if (inst.is_ideal_jump()) {
fprintf(fp, " _constant = C->constant_table().add_jump_table(this);\n"); fprintf(fp, " _constant = C->output()->constant_table().add_jump_table(this);\n");
} }
// If user did not define an encode section, // If user did not define an encode section,

View file

@ -395,6 +395,9 @@ public:
return _compiler2_objects[idx]; return _compiler2_objects[idx];
} }
static AbstractCompiler* compiler1() { return _compilers[0]; }
static AbstractCompiler* compiler2() { return _compilers[1]; }
static bool can_remove(CompilerThread *ct, bool do_it); static bool can_remove(CompilerThread *ct, bool do_it);
static CompileLog* get_log(CompilerThread* ct); static CompileLog* get_log(CompilerThread* ct);

View file

@ -36,6 +36,7 @@
#include "opto/macro.hpp" #include "opto/macro.hpp"
#include "opto/memnode.hpp" #include "opto/memnode.hpp"
#include "opto/node.hpp" #include "opto/node.hpp"
#include "opto/output.hpp"
#include "opto/regalloc.hpp" #include "opto/regalloc.hpp"
#include "opto/rootnode.hpp" #include "opto/rootnode.hpp"
#include "opto/type.hpp" #include "opto/type.hpp"
@ -85,7 +86,7 @@ static ZBarrierSetC2State* barrier_set_state() {
ZLoadBarrierStubC2* ZLoadBarrierStubC2::create(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) { ZLoadBarrierStubC2* ZLoadBarrierStubC2::create(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak) {
ZLoadBarrierStubC2* const stub = new (Compile::current()->comp_arena()) ZLoadBarrierStubC2(node, ref_addr, ref, tmp, weak); ZLoadBarrierStubC2* const stub = new (Compile::current()->comp_arena()) ZLoadBarrierStubC2(node, ref_addr, ref, tmp, weak);
if (!Compile::current()->in_scratch_emit_size()) { if (!Compile::current()->output()->in_scratch_emit_size()) {
barrier_set_state()->stubs()->append(stub); barrier_set_state()->stubs()->append(stub);
} }
@ -130,7 +131,7 @@ Label* ZLoadBarrierStubC2::entry() {
// However, we still need to return a label that is not bound now, but // However, we still need to return a label that is not bound now, but
// will eventually be bound. Any lable will do, as it will only act as // will eventually be bound. Any lable will do, as it will only act as
// a placeholder, so we return the _continuation label. // a placeholder, so we return the _continuation label.
return Compile::current()->in_scratch_emit_size() ? &_continuation : &_entry; return Compile::current()->output()->in_scratch_emit_size() ? &_continuation : &_entry;
} }
Label* ZLoadBarrierStubC2::continuation() { Label* ZLoadBarrierStubC2::continuation() {
@ -152,7 +153,7 @@ void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const {
for (int i = 0; i < stubs->length(); i++) { for (int i = 0; i < stubs->length(); i++) {
// Make sure there is enough space in the code buffer // Make sure there is enough space in the code buffer
if (cb.insts()->maybe_expand_to_ensure_remaining(Compile::MAX_inst_size) && cb.blob() == NULL) { if (cb.insts()->maybe_expand_to_ensure_remaining(PhaseOutput::MAX_inst_size) && cb.blob() == NULL) {
ciEnv::current()->record_failure("CodeCache is full"); ciEnv::current()->record_failure("CodeCache is full");
return; return;
} }
@ -165,12 +166,12 @@ void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const {
int ZBarrierSetC2::estimate_stub_size() const { int ZBarrierSetC2::estimate_stub_size() const {
Compile* const C = Compile::current(); Compile* const C = Compile::current();
BufferBlob* const blob = C->scratch_buffer_blob(); BufferBlob* const blob = C->output()->scratch_buffer_blob();
GrowableArray<ZLoadBarrierStubC2*>* const stubs = barrier_set_state()->stubs(); GrowableArray<ZLoadBarrierStubC2*>* const stubs = barrier_set_state()->stubs();
int size = 0; int size = 0;
for (int i = 0; i < stubs->length(); i++) { for (int i = 0; i < stubs->length(); i++) {
CodeBuffer cb(blob->content_begin(), (address)C->scratch_locs_memory() - blob->content_begin()); CodeBuffer cb(blob->content_begin(), (address)C->output()->scratch_locs_memory() - blob->content_begin());
MacroAssembler masm(&cb); MacroAssembler masm(&cb);
ZBarrierSet::assembler()->generate_c2_load_barrier_stub(&masm, stubs->at(i)); ZBarrierSet::assembler()->generate_c2_load_barrier_stub(&masm, stubs->at(i));
size += cb.insts_size(); size += cb.insts_size();

View file

@ -31,6 +31,7 @@
#include "opto/compile.hpp" #include "opto/compile.hpp"
#include "opto/machnode.hpp" #include "opto/machnode.hpp"
#include "opto/matcher.hpp" #include "opto/matcher.hpp"
#include "opto/output.hpp"
#include "opto/phase.hpp" #include "opto/phase.hpp"
#include "opto/regalloc.hpp" #include "opto/regalloc.hpp"
#include "opto/rootnode.hpp" #include "opto/rootnode.hpp"
@ -563,12 +564,12 @@ static void do_liveness(PhaseRegAlloc* regalloc, PhaseCFG* cfg, Block_List* work
} }
// Collect GC mask info - where are all the OOPs? // Collect GC mask info - where are all the OOPs?
void Compile::BuildOopMaps() { void PhaseOutput::BuildOopMaps() {
TracePhase tp("bldOopMaps", &timers[_t_buildOopMaps]); Compile::TracePhase tp("bldOopMaps", &timers[_t_buildOopMaps]);
// Can't resource-mark because I need to leave all those OopMaps around, // Can't resource-mark because I need to leave all those OopMaps around,
// or else I need to resource-mark some arena other than the default. // or else I need to resource-mark some arena other than the default.
// ResourceMark rm; // Reclaim all OopFlows when done // ResourceMark rm; // Reclaim all OopFlows when done
int max_reg = _regalloc->_max_reg; // Current array extent int max_reg = C->regalloc()->_max_reg; // Current array extent
Arena *A = Thread::current()->resource_area(); Arena *A = Thread::current()->resource_area();
Block_List worklist; // Worklist of pending blocks Block_List worklist; // Worklist of pending blocks
@ -578,17 +579,17 @@ void Compile::BuildOopMaps() {
// Compute a backwards liveness per register. Needs a bitarray of // Compute a backwards liveness per register. Needs a bitarray of
// #blocks x (#registers, rounded up to ints) // #blocks x (#registers, rounded up to ints)
safehash = new Dict(cmpkey,hashkey,A); safehash = new Dict(cmpkey,hashkey,A);
do_liveness( _regalloc, _cfg, &worklist, max_reg_ints, A, safehash ); do_liveness( C->regalloc(), C->cfg(), &worklist, max_reg_ints, A, safehash );
OopFlow *free_list = NULL; // Free, unused OopFlow *free_list = NULL; // Free, unused
// Array mapping blocks to completed oopflows // Array mapping blocks to completed oopflows
OopFlow **flows = NEW_ARENA_ARRAY(A, OopFlow*, _cfg->number_of_blocks()); OopFlow **flows = NEW_ARENA_ARRAY(A, OopFlow*, C->cfg()->number_of_blocks());
memset( flows, 0, _cfg->number_of_blocks() * sizeof(OopFlow*) ); memset( flows, 0, C->cfg()->number_of_blocks() * sizeof(OopFlow*) );
// Do the first block 'by hand' to prime the worklist // Do the first block 'by hand' to prime the worklist
Block *entry = _cfg->get_block(1); Block *entry = C->cfg()->get_block(1);
OopFlow *rootflow = OopFlow::make(A,max_reg,this); OopFlow *rootflow = OopFlow::make(A,max_reg,C);
// Initialize to 'bottom' (not 'top') // Initialize to 'bottom' (not 'top')
memset( rootflow->_callees, OptoReg::Bad, max_reg*sizeof(short) ); memset( rootflow->_callees, OptoReg::Bad, max_reg*sizeof(short) );
memset( rootflow->_defs , 0, max_reg*sizeof(Node*) ); memset( rootflow->_defs , 0, max_reg*sizeof(Node*) );
@ -596,7 +597,7 @@ void Compile::BuildOopMaps() {
// Do the first block 'by hand' to prime the worklist // Do the first block 'by hand' to prime the worklist
rootflow->_b = entry; rootflow->_b = entry;
rootflow->compute_reach( _regalloc, max_reg, safehash ); rootflow->compute_reach( C->regalloc(), max_reg, safehash );
for( uint i=0; i<entry->_num_succs; i++ ) for( uint i=0; i<entry->_num_succs; i++ )
worklist.push(entry->_succs[i]); worklist.push(entry->_succs[i]);
@ -613,7 +614,7 @@ void Compile::BuildOopMaps() {
Block *b = worklist.pop(); Block *b = worklist.pop();
// Ignore root block // Ignore root block
if (b == _cfg->get_root_block()) { if (b == C->cfg()->get_root_block()) {
continue; continue;
} }
// Block is already done? Happens if block has several predecessors, // Block is already done? Happens if block has several predecessors,
@ -627,7 +628,7 @@ void Compile::BuildOopMaps() {
Block *pred = (Block*)((intptr_t)0xdeadbeef); Block *pred = (Block*)((intptr_t)0xdeadbeef);
// Scan this block's preds to find a done predecessor // Scan this block's preds to find a done predecessor
for (uint j = 1; j < b->num_preds(); j++) { for (uint j = 1; j < b->num_preds(); j++) {
Block* p = _cfg->get_block_for_node(b->pred(j)); Block* p = C->cfg()->get_block_for_node(b->pred(j));
OopFlow *p_flow = flows[p->_pre_order]; OopFlow *p_flow = flows[p->_pre_order];
if( p_flow ) { // Predecessor is done if( p_flow ) { // Predecessor is done
assert( p_flow->_b == p, "cross check" ); assert( p_flow->_b == p, "cross check" );
@ -674,7 +675,7 @@ void Compile::BuildOopMaps() {
// Now push flow forward // Now push flow forward
flows[b->_pre_order] = flow;// Mark flow for this block flows[b->_pre_order] = flow;// Mark flow for this block
flow->_b = b; flow->_b = b;
flow->compute_reach( _regalloc, max_reg, safehash ); flow->compute_reach( C->regalloc(), max_reg, safehash );
// Now push children onto worklist // Now push children onto worklist
for( i=0; i<b->_num_succs; i++ ) for( i=0; i<b->_num_succs; i++ )

View file

@ -108,7 +108,7 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, Dir
while (!env->failing()) { while (!env->failing()) {
// Attempt to compile while subsuming loads into machine instructions. // Attempt to compile while subsuming loads into machine instructions.
Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive); Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
// Check result and retry if appropriate. // Check result and retry if appropriate.
if (C.failure_reason() != NULL) { if (C.failure_reason() != NULL) {
@ -652,7 +652,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
int C2Compiler::initial_code_buffer_size(int const_size) { int C2Compiler::initial_code_buffer_size(int const_size) {
// See Compile::init_scratch_buffer_blob // See Compile::init_scratch_buffer_blob
int locs_size = sizeof(relocInfo) * Compile::MAX_locs_size; int locs_size = sizeof(relocInfo) * PhaseOutput::MAX_locs_size;
int slop = 2 * CodeSection::end_slop(); // space between sections int slop = 2 * CodeSection::end_slop(); // space between sections
return Compile::MAX_inst_size + Compile::MAX_stubs_size + const_size + slop + locs_size; return PhaseOutput::MAX_inst_size + PhaseOutput::MAX_stubs_size + const_size + slop + locs_size;
} }

View file

@ -29,11 +29,11 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "opto/connode.hpp" #include "opto/connode.hpp"
#include "opto/live.hpp" #include "opto/live.hpp"
#include "opto/machnode.hpp"
#include "opto/matcher.hpp" #include "opto/matcher.hpp"
#include "opto/phase.hpp" #include "opto/phase.hpp"
#include "opto/regalloc.hpp" #include "opto/regalloc.hpp"
#include "opto/regmask.hpp" #include "opto/regmask.hpp"
#include "opto/machnode.hpp"
class Matcher; class Matcher;
class PhaseCFG; class PhaseCFG;

View file

@ -250,7 +250,7 @@ void Compile::print_statistics() {
Parse::print_statistics(); Parse::print_statistics();
PhaseCCP::print_statistics(); PhaseCCP::print_statistics();
PhaseRegAlloc::print_statistics(); PhaseRegAlloc::print_statistics();
Scheduling::print_statistics(); PhaseOutput::print_statistics();
PhasePeephole::print_statistics(); PhasePeephole::print_statistics();
PhaseIdealLoop::print_statistics(); PhaseIdealLoop::print_statistics();
if (xtty != NULL) xtty->tail("statistics"); if (xtty != NULL) xtty->tail("statistics");
@ -262,17 +262,6 @@ void Compile::print_statistics() {
} }
#endif //PRODUCT #endif //PRODUCT
// Support for bundling info
Bundle* Compile::node_bundling(const Node *n) {
assert(valid_bundle_info(n), "oob");
return &_node_bundling_base[n->_idx];
}
bool Compile::valid_bundle_info(const Node *n) {
return (_node_bundling_limit > n->_idx);
}
void Compile::gvn_replace_by(Node* n, Node* nn) { void Compile::gvn_replace_by(Node* n, Node* nn) {
for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) { for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) {
Node* use = n->last_out(i); Node* use = n->last_out(i);
@ -423,24 +412,6 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
debug_only(verify_graph_edges(true/*check for no_dead_code*/);) debug_only(verify_graph_edges(true/*check for no_dead_code*/);)
} }
//------------------------------frame_size_in_words-----------------------------
// frame_slots in units of words
int Compile::frame_size_in_words() const {
// shift is 0 in LP32 and 1 in LP64
const int shift = (LogBytesPerWord - LogBytesPerInt);
int words = _frame_slots >> shift;
assert( words << shift == _frame_slots, "frame size must be properly aligned in LP64" );
return words;
}
// To bang the stack of this compiled method we use the stack size
// that the interpreter would need in case of a deoptimization. This
// removes the need to bang the stack in the deoptimization blob which
// in turn simplifies stack overflow handling.
int Compile::bang_size_in_bytes() const {
return MAX2(frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _interpreter_frame_size);
}
// ============================================================================ // ============================================================================
//------------------------------CompileWrapper--------------------------------- //------------------------------CompileWrapper---------------------------------
class CompileWrapper : public StackObj { class CompileWrapper : public StackObj {
@ -468,14 +439,11 @@ CompileWrapper::CompileWrapper(Compile* compile) : _compile(compile) {
compile->set_indexSet_free_block_list(NULL); compile->set_indexSet_free_block_list(NULL);
compile->init_type_arena(); compile->init_type_arena();
Type::Initialize(compile); Type::Initialize(compile);
_compile->set_scratch_buffer_blob(NULL);
_compile->begin_method(); _compile->begin_method();
_compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption); _compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
} }
CompileWrapper::~CompileWrapper() { CompileWrapper::~CompileWrapper() {
_compile->end_method(); _compile->end_method();
if (_compile->scratch_buffer_blob() != NULL)
BufferBlob::free(_compile->scratch_buffer_blob());
_compile->env()->set_compiler_data(NULL); _compile->env()->set_compiler_data(NULL);
} }
@ -520,104 +488,6 @@ void Compile::print_compile_messages() {
#endif #endif
} }
//-----------------------init_scratch_buffer_blob------------------------------
// Construct a temporary BufferBlob and cache it for this compile.
void Compile::init_scratch_buffer_blob(int const_size) {
// If there is already a scratch buffer blob allocated and the
// constant section is big enough, use it. Otherwise free the
// current and allocate a new one.
BufferBlob* blob = scratch_buffer_blob();
if ((blob != NULL) && (const_size <= _scratch_const_size)) {
// Use the current blob.
} else {
if (blob != NULL) {
BufferBlob::free(blob);
}
ResourceMark rm;
_scratch_const_size = const_size;
int size = C2Compiler::initial_code_buffer_size(const_size);
blob = BufferBlob::create("Compile::scratch_buffer", size);
// Record the buffer blob for next time.
set_scratch_buffer_blob(blob);
// Have we run out of code space?
if (scratch_buffer_blob() == NULL) {
// Let CompilerBroker disable further compilations.
record_failure("Not enough space for scratch buffer in CodeCache");
return;
}
}
// Initialize the relocation buffers
relocInfo* locs_buf = (relocInfo*) blob->content_end() - MAX_locs_size;
set_scratch_locs_memory(locs_buf);
}
//-----------------------scratch_emit_size-------------------------------------
// Helper function that computes size by emitting code
uint Compile::scratch_emit_size(const Node* n) {
// Start scratch_emit_size section.
set_in_scratch_emit_size(true);
// Emit into a trash buffer and count bytes emitted.
// This is a pretty expensive way to compute a size,
// but it works well enough if seldom used.
// All common fixed-size instructions are given a size
// method by the AD file.
// Note that the scratch buffer blob and locs memory are
// allocated at the beginning of the compile task, and
// may be shared by several calls to scratch_emit_size.
// The allocation of the scratch buffer blob is particularly
// expensive, since it has to grab the code cache lock.
BufferBlob* blob = this->scratch_buffer_blob();
assert(blob != NULL, "Initialize BufferBlob at start");
assert(blob->size() > MAX_inst_size, "sanity");
relocInfo* locs_buf = scratch_locs_memory();
address blob_begin = blob->content_begin();
address blob_end = (address)locs_buf;
assert(blob->contains(blob_end), "sanity");
CodeBuffer buf(blob_begin, blob_end - blob_begin);
buf.initialize_consts_size(_scratch_const_size);
buf.initialize_stubs_size(MAX_stubs_size);
assert(locs_buf != NULL, "sanity");
int lsize = MAX_locs_size / 3;
buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize);
buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], 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.
Label fakeL; // Fake label for branch instructions.
Label* saveL = NULL;
uint save_bnum = 0;
bool is_branch = n->is_MachBranch();
if (is_branch) {
MacroAssembler masm(&buf);
masm.bind(fakeL);
n->as_MachBranch()->save_label(&saveL, &save_bnum);
n->as_MachBranch()->label_set(&fakeL, 0);
}
n->emit(buf, this->regalloc());
// Emitting into the scratch buffer should not fail
assert (!failing(), "Must not have pending failure. Reason is: %s", failure_reason());
if (is_branch) // Restore label.
n->as_MachBranch()->label_set(saveL, save_bnum);
// End scratch_emit_size section.
set_in_scratch_emit_size(false);
return buf.insts_size();
}
// ============================================================================ // ============================================================================
//------------------------------Compile standard------------------------------- //------------------------------Compile standard-------------------------------
debug_only( int Compile::_debug_idx = 100000; ) debug_only( int Compile::_debug_idx = 100000; )
@ -626,7 +496,7 @@ debug_only( int Compile::_debug_idx = 100000; )
// the continuation bci for on stack replacement. // the continuation bci for on stack replacement.
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive) bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
: Phase(Compiler), : Phase(Compiler),
_compile_id(ci_env->compile_id()), _compile_id(ci_env->compile_id()),
@ -640,8 +510,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_stub_name(NULL), _stub_name(NULL),
_stub_entry_point(NULL), _stub_entry_point(NULL),
_max_node_limit(MaxNodeLimit), _max_node_limit(MaxNodeLimit),
_orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0),
_inlining_progress(false), _inlining_progress(false),
_inlining_incrementally(false), _inlining_incrementally(false),
_do_cleanup(false), _do_cleanup(false),
@ -683,12 +551,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_replay_inline_data(NULL), _replay_inline_data(NULL),
_java_calls(0), _java_calls(0),
_inner_loops(0), _inner_loops(0),
_interpreter_frame_size(0), _interpreter_frame_size(0)
_node_bundling_limit(0),
_node_bundling_base(NULL),
_code_buffer("Compile::Fill_buffer"),
_scratch_const_size(-1),
_in_scratch_emit_size(false)
#ifndef PRODUCT #ifndef PRODUCT
, _in_dump_cnt(0) , _in_dump_cnt(0)
#endif #endif
@ -906,9 +769,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
// Now that we know the size of all the monitors we can add a fixed slot // Now that we know the size of all the monitors we can add a fixed slot
// for the original deopt pc. // for the original deopt pc.
int next_slot = fixed_slots() + (sizeof(address) / VMRegImpl::stack_slot_size);
_orig_pc_slot = fixed_slots();
int next_slot = _orig_pc_slot + (sizeof(address) / VMRegImpl::stack_slot_size);
set_fixed_slots(next_slot); set_fixed_slots(next_slot);
// Compute when to use implicit null checks. Used by matching trap based // Compute when to use implicit null checks. Used by matching trap based
@ -917,41 +778,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
// Now generate code // Now generate code
Code_Gen(); Code_Gen();
if (failing()) return;
// Check if we want to skip execution of all compiled code.
{
#ifndef PRODUCT
if (OptoNoExecute) {
record_method_not_compilable("+OptoNoExecute"); // Flag as failed
return;
}
#endif
TracePhase tp("install_code", &timers[_t_registerMethod]);
if (is_osr_compilation()) {
_code_offsets.set_value(CodeOffsets::Verified_Entry, 0);
_code_offsets.set_value(CodeOffsets::OSR_Entry, _first_block_size);
} else {
_code_offsets.set_value(CodeOffsets::Verified_Entry, _first_block_size);
_code_offsets.set_value(CodeOffsets::OSR_Entry, 0);
}
env()->register_method(_method, _entry_bci,
&_code_offsets,
_orig_pc_slot_offset_in_bytes,
code_buffer(),
frame_size_in_words(), _oop_map_set,
&_handler_table, &_inc_table,
compiler,
has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size()),
rtm_state()
);
if (log() != NULL) // Print code cache state into compiler log
log()->code_cache_state();
}
} }
//------------------------------Compile---------------------------------------- //------------------------------Compile----------------------------------------
@ -977,8 +803,6 @@ Compile::Compile( ciEnv* ci_env,
_stub_name(stub_name), _stub_name(stub_name),
_stub_entry_point(NULL), _stub_entry_point(NULL),
_max_node_limit(MaxNodeLimit), _max_node_limit(MaxNodeLimit),
_orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0),
_inlining_progress(false), _inlining_progress(false),
_inlining_incrementally(false), _inlining_incrementally(false),
_has_reserved_stack_access(false), _has_reserved_stack_access(false),
@ -1016,9 +840,6 @@ Compile::Compile( ciEnv* ci_env,
_java_calls(0), _java_calls(0),
_inner_loops(0), _inner_loops(0),
_interpreter_frame_size(0), _interpreter_frame_size(0),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_code_buffer("Compile::Fill_buffer"),
#ifndef PRODUCT #ifndef PRODUCT
_in_dump_cnt(0), _in_dump_cnt(0),
#endif #endif
@ -1053,34 +874,8 @@ Compile::Compile( ciEnv* ci_env,
} }
NOT_PRODUCT( verify_graph_edges(); ) NOT_PRODUCT( verify_graph_edges(); )
Code_Gen(); Code_Gen();
if (failing()) return;
// Entry point will be accessed using compile->stub_entry_point();
if (code_buffer() == NULL) {
Matcher::soft_match_failure();
} else {
if (PrintAssembly && (WizardMode || Verbose))
tty->print_cr("### Stub::%s", stub_name);
if (!failing()) {
assert(_fixed_slots == 0, "no fixed slots used for runtime stubs");
// Make the NMethod
// For now we mark the frame as never safe for profile stackwalking
RuntimeStub *rs = RuntimeStub::new_runtime_stub(stub_name,
code_buffer(),
CodeOffsets::frame_never_safe,
// _code_offsets.value(CodeOffsets::Frame_Complete),
frame_size_in_words(),
_oop_map_set,
save_arg_registers);
assert(rs != NULL && rs->is_runtime_stub(), "sanity check");
_stub_entry_point = rs->entry_point();
}
}
} }
//------------------------------Init------------------------------------------- //------------------------------Init-------------------------------------------
@ -2545,8 +2340,11 @@ void Compile::Code_Gen() {
// Convert Nodes to instruction bits in a buffer // Convert Nodes to instruction bits in a buffer
{ {
TraceTime tp("output", &timers[_t_output], CITime); TracePhase tp("output", &timers[_t_output]);
Output(); PhaseOutput output;
output.Output();
if (failing()) return;
output.install();
} }
print_method(PHASE_FINAL_CODE); print_method(PHASE_FINAL_CODE);
@ -2556,143 +2354,6 @@ void Compile::Code_Gen() {
_regalloc = (PhaseChaitin*)((intptr_t)0xdeadbeef); _regalloc = (PhaseChaitin*)((intptr_t)0xdeadbeef);
} }
//------------------------------dump_asm---------------------------------------
// Dump formatted assembly
#if defined(SUPPORT_OPTO_ASSEMBLY)
void Compile::dump_asm_on(outputStream* st, int* pcs, uint pc_limit) {
int pc_digits = 3; // #chars required for pc
int sb_chars = 3; // #chars for "start bundle" indicator
int tab_size = 8;
if (pcs != NULL) {
int max_pc = 0;
for (uint i = 0; i < pc_limit; i++) {
max_pc = (max_pc < pcs[i]) ? pcs[i] : max_pc;
}
pc_digits = ((max_pc < 4096) ? 3 : ((max_pc < 65536) ? 4 : ((max_pc < 65536*256) ? 6 : 8))); // #chars required for pc
}
int prefix_len = ((pc_digits + sb_chars + tab_size - 1)/tab_size)*tab_size;
bool cut_short = false;
st->print_cr("#");
st->print("# "); _tf->dump_on(st); st->cr();
st->print_cr("#");
// For all blocks
int pc = 0x0; // Program counter
char starts_bundle = ' ';
_regalloc->dump_frame();
Node *n = NULL;
for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
if (VMThread::should_terminate()) {
cut_short = true;
break;
}
Block* block = _cfg->get_block(i);
if (block->is_connector() && !Verbose) {
continue;
}
n = block->head();
if ((pcs != NULL) && (n->_idx < pc_limit)) {
pc = pcs[n->_idx];
st->print("%*.*x", pc_digits, pc_digits, pc);
}
st->fill_to(prefix_len);
block->dump_head(_cfg, st);
if (block->is_connector()) {
st->fill_to(prefix_len);
st->print_cr("# Empty connector block");
} else if (block->num_preds() == 2 && block->pred(1)->is_CatchProj() && block->pred(1)->as_CatchProj()->_con == CatchProjNode::fall_through_index) {
st->fill_to(prefix_len);
st->print_cr("# Block is sole successor of call");
}
// For all instructions
Node *delay = NULL;
for (uint j = 0; j < block->number_of_nodes(); j++) {
if (VMThread::should_terminate()) {
cut_short = true;
break;
}
n = block->get_node(j);
if (valid_bundle_info(n)) {
Bundle* bundle = node_bundling(n);
if (bundle->used_in_unconditional_delay()) {
delay = n;
continue;
}
if (bundle->starts_bundle()) {
starts_bundle = '+';
}
}
if (WizardMode) {
n->dump();
}
if( !n->is_Region() && // Dont print in the Assembly
!n->is_Phi() && // a few noisely useless nodes
!n->is_Proj() &&
!n->is_MachTemp() &&
!n->is_SafePointScalarObject() &&
!n->is_Catch() && // Would be nice to print exception table targets
!n->is_MergeMem() && // Not very interesting
!n->is_top() && // Debug info table constants
!(n->is_Con() && !n->is_Mach())// Debug info table constants
) {
if ((pcs != NULL) && (n->_idx < pc_limit)) {
pc = pcs[n->_idx];
st->print("%*.*x", pc_digits, pc_digits, pc);
} else {
st->fill_to(pc_digits);
}
st->print(" %c ", starts_bundle);
starts_bundle = ' ';
st->fill_to(prefix_len);
n->format(_regalloc, st);
st->cr();
}
// If we have an instruction with a delay slot, and have seen a delay,
// then back up and print it
if (valid_bundle_info(n) && node_bundling(n)->use_unconditional_delay()) {
// Coverity finding - Explicit null dereferenced.
guarantee(delay != NULL, "no unconditional delay instruction");
if (WizardMode) delay->dump();
if (node_bundling(delay)->starts_bundle())
starts_bundle = '+';
if ((pcs != NULL) && (n->_idx < pc_limit)) {
pc = pcs[n->_idx];
st->print("%*.*x", pc_digits, pc_digits, pc);
} else {
st->fill_to(pc_digits);
}
st->print(" %c ", starts_bundle);
starts_bundle = ' ';
st->fill_to(prefix_len);
delay->format(_regalloc, st);
st->cr();
delay = NULL;
}
// Dump the exception table as well
if( n->is_Catch() && (Verbose || WizardMode) ) {
// Print the exception table for this offset
_handler_table.print_subtable_for(pc);
}
st->bol(); // Make sure we start on a new line
}
st->cr(); // one empty line between blocks
assert(cut_short || delay == NULL, "no unconditional delay branch");
} // End of per-block dump
if (cut_short) st->print_cr("*** disassembly is cut short ***");
}
#endif
//------------------------------Final_Reshape_Counts--------------------------- //------------------------------Final_Reshape_Counts---------------------------
// This class defines counters to help identify when a method // This class defines counters to help identify when a method
// may/must be executed using hardware with only 24-bit precision. // may/must be executed using hardware with only 24-bit precision.
@ -3985,222 +3646,6 @@ Compile::TracePhase::~TracePhase() {
} }
} }
//=============================================================================
// Two Constant's are equal when the type and the value are equal.
bool Compile::Constant::operator==(const Constant& other) {
if (type() != other.type() ) return false;
if (can_be_reused() != other.can_be_reused()) return false;
// For floating point values we compare the bit pattern.
switch (type()) {
case T_INT:
case T_FLOAT: return (_v._value.i == other._v._value.i);
case T_LONG:
case T_DOUBLE: return (_v._value.j == other._v._value.j);
case T_OBJECT:
case T_ADDRESS: return (_v._value.l == other._v._value.l);
case T_VOID: return (_v._value.l == other._v._value.l); // jump-table entries
case T_METADATA: return (_v._metadata == other._v._metadata);
default: ShouldNotReachHere(); return false;
}
}
static int type_to_size_in_bytes(BasicType t) {
switch (t) {
case T_INT: return sizeof(jint );
case T_LONG: return sizeof(jlong );
case T_FLOAT: return sizeof(jfloat );
case T_DOUBLE: return sizeof(jdouble);
case T_METADATA: return sizeof(Metadata*);
// We use T_VOID as marker for jump-table entries (labels) which
// need an internal word relocation.
case T_VOID:
case T_ADDRESS:
case T_OBJECT: return sizeof(jobject);
default:
ShouldNotReachHere();
return -1;
}
}
int Compile::ConstantTable::qsort_comparator(Constant* a, Constant* b) {
// sort descending
if (a->freq() > b->freq()) return -1;
if (a->freq() < b->freq()) return 1;
return 0;
}
void Compile::ConstantTable::calculate_offsets_and_size() {
// First, sort the array by frequencies.
_constants.sort(qsort_comparator);
#ifdef ASSERT
// Make sure all jump-table entries were sorted to the end of the
// array (they have a negative frequency).
bool found_void = false;
for (int i = 0; i < _constants.length(); i++) {
Constant con = _constants.at(i);
if (con.type() == T_VOID)
found_void = true; // jump-tables
else
assert(!found_void, "wrong sorting");
}
#endif
int offset = 0;
for (int i = 0; i < _constants.length(); i++) {
Constant* con = _constants.adr_at(i);
// Align offset for type.
int typesize = type_to_size_in_bytes(con->type());
offset = align_up(offset, typesize);
con->set_offset(offset); // set constant's offset
if (con->type() == T_VOID) {
MachConstantNode* n = (MachConstantNode*) con->get_jobject();
offset = offset + typesize * n->outcnt(); // expand jump-table
} else {
offset = offset + typesize;
}
}
// Align size up to the next section start (which is insts; see
// CodeBuffer::align_at_start).
assert(_size == -1, "already set?");
_size = align_up(offset, (int)CodeEntryAlignment);
}
void Compile::ConstantTable::emit(CodeBuffer& cb) {
MacroAssembler _masm(&cb);
for (int i = 0; i < _constants.length(); i++) {
Constant con = _constants.at(i);
address constant_addr = NULL;
switch (con.type()) {
case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break;
case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;
case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break;
case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
case T_OBJECT: {
jobject obj = con.get_jobject();
int oop_index = _masm.oop_recorder()->find_index(obj);
constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
break;
}
case T_ADDRESS: {
address addr = (address) con.get_jobject();
constant_addr = _masm.address_constant(addr);
break;
}
// We use T_VOID as marker for jump-table entries (labels) which
// need an internal word relocation.
case T_VOID: {
MachConstantNode* n = (MachConstantNode*) con.get_jobject();
// Fill the jump-table with a dummy word. The real value is
// filled in later in fill_jump_table.
address dummy = (address) n;
constant_addr = _masm.address_constant(dummy);
// Expand jump-table
for (uint i = 1; i < n->outcnt(); i++) {
address temp_addr = _masm.address_constant(dummy + i);
assert(temp_addr, "consts section too small");
}
break;
}
case T_METADATA: {
Metadata* obj = con.get_metadata();
int metadata_index = _masm.oop_recorder()->find_index(obj);
constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index));
break;
}
default: ShouldNotReachHere();
}
assert(constant_addr, "consts section too small");
assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),
"must be: %d == %d", (int) (constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));
}
}
int Compile::ConstantTable::find_offset(Constant& con) const {
int idx = _constants.find(con);
guarantee(idx != -1, "constant must be in constant table");
int offset = _constants.at(idx).offset();
guarantee(offset != -1, "constant table not emitted yet?");
return offset;
}
void Compile::ConstantTable::add(Constant& con) {
if (con.can_be_reused()) {
int idx = _constants.find(con);
if (idx != -1 && _constants.at(idx).can_be_reused()) {
_constants.adr_at(idx)->inc_freq(con.freq()); // increase the frequency by the current value
return;
}
}
(void) _constants.append(con);
}
Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
Block* b = Compile::current()->cfg()->get_block_for_node(n);
Constant con(type, value, b->_freq);
add(con);
return con;
}
Compile::Constant Compile::ConstantTable::add(Metadata* metadata) {
Constant con(metadata);
add(con);
return con;
}
Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) {
jvalue value;
BasicType type = oper->type()->basic_type();
switch (type) {
case T_LONG: value.j = oper->constantL(); break;
case T_FLOAT: value.f = oper->constantF(); break;
case T_DOUBLE: value.d = oper->constantD(); break;
case T_OBJECT:
case T_ADDRESS: value.l = (jobject) oper->constant(); break;
case T_METADATA: return add((Metadata*)oper->constant()); break;
default: guarantee(false, "unhandled type: %s", type2name(type));
}
return add(n, type, value);
}
Compile::Constant Compile::ConstantTable::add_jump_table(MachConstantNode* n) {
jvalue value;
// We can use the node pointer here to identify the right jump-table
// as this method is called from Compile::Fill_buffer right before
// the MachNodes are emitted and the jump-table is filled (means the
// MachNode pointers do not change anymore).
value.l = (jobject) n;
Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused.
add(con);
return con;
}
void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {
// If called from Compile::scratch_emit_size do nothing.
if (Compile::current()->in_scratch_emit_size()) return;
assert(labels.is_nonempty(), "must be");
assert((uint) labels.length() == n->outcnt(), "must be equal: %d == %d", labels.length(), n->outcnt());
// Since MachConstantNode::constant_offset() also contains
// table_base_offset() we need to subtract the table_base_offset()
// to get the plain offset into the constant table.
int offset = n->constant_offset() - table_base_offset();
MacroAssembler _masm(&cb);
address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
for (uint i = 0; i < n->outcnt(); i++) {
address* constant_addr = &jump_table_base[i];
assert(*constant_addr == (((address) n) + i), "all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, p2i(*constant_addr), p2i(((address) n) + i));
*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
}
}
//----------------------------static_subtype_check----------------------------- //----------------------------static_subtype_check-----------------------------
// Shortcut important common cases when superklass is exact: // Shortcut important common cases when superklass is exact:
// (0) superklass is java.lang.Object (can occur in reflective code) // (0) superklass is java.lang.Object (can occur in reflective code)

View file

@ -28,7 +28,6 @@
#include "asm/codeBuffer.hpp" #include "asm/codeBuffer.hpp"
#include "ci/compilerInterface.hpp" #include "ci/compilerInterface.hpp"
#include "code/debugInfoRec.hpp" #include "code/debugInfoRec.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "compiler/compilerOracle.hpp" #include "compiler/compilerOracle.hpp"
#include "compiler/compileBroker.hpp" #include "compiler/compileBroker.hpp"
#include "libadt/dict.hpp" #include "libadt/dict.hpp"
@ -48,7 +47,6 @@
class AddPNode; class AddPNode;
class Block; class Block;
class Bundle; class Bundle;
class C2Compiler;
class CallGenerator; class CallGenerator;
class CloneMap; class CloneMap;
class ConnectionGraph; class ConnectionGraph;
@ -72,6 +70,7 @@ class PhaseIterGVN;
class PhaseRegAlloc; class PhaseRegAlloc;
class PhaseCCP; class PhaseCCP;
class PhaseCCP_DCE; class PhaseCCP_DCE;
class PhaseOutput;
class RootNode; class RootNode;
class relocInfo; class relocInfo;
class Scope; class Scope;
@ -240,121 +239,6 @@ class Compile : public Phase {
trapHistLength = MethodData::_trap_hist_limit trapHistLength = MethodData::_trap_hist_limit
}; };
// Constant entry of the constant table.
class Constant {
private:
BasicType _type;
union {
jvalue _value;
Metadata* _metadata;
} _v;
int _offset; // offset of this constant (in bytes) relative to the constant table base.
float _freq;
bool _can_be_reused; // true (default) if the value can be shared with other users.
public:
Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; }
Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) :
_type(type),
_offset(-1),
_freq(freq),
_can_be_reused(can_be_reused)
{
assert(type != T_METADATA, "wrong constructor");
_v._value = value;
}
Constant(Metadata* metadata, bool can_be_reused = true) :
_type(T_METADATA),
_offset(-1),
_freq(0.0f),
_can_be_reused(can_be_reused)
{
_v._metadata = metadata;
}
bool operator==(const Constant& other);
BasicType type() const { return _type; }
jint get_jint() const { return _v._value.i; }
jlong get_jlong() const { return _v._value.j; }
jfloat get_jfloat() const { return _v._value.f; }
jdouble get_jdouble() const { return _v._value.d; }
jobject get_jobject() const { return _v._value.l; }
Metadata* get_metadata() const { return _v._metadata; }
int offset() const { return _offset; }
void set_offset(int offset) { _offset = offset; }
float freq() const { return _freq; }
void inc_freq(float freq) { _freq += freq; }
bool can_be_reused() const { return _can_be_reused; }
};
// Constant table.
class ConstantTable {
private:
GrowableArray<Constant> _constants; // Constants of this table.
int _size; // Size in bytes the emitted constant table takes (including padding).
int _table_base_offset; // Offset of the table base that gets added to the constant offsets.
int _nof_jump_tables; // Number of jump-tables in this constant table.
static int qsort_comparator(Constant* a, Constant* b);
// We use negative frequencies to keep the order of the
// jump-tables in which they were added. Otherwise we get into
// trouble with relocation.
float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); }
public:
ConstantTable() :
_size(-1),
_table_base_offset(-1), // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
_nof_jump_tables(0)
{}
int size() const { assert(_size != -1, "not calculated yet"); return _size; }
int calculate_table_base_offset() const; // AD specific
void set_table_base_offset(int x) { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; }
int table_base_offset() const { assert(_table_base_offset != -1, "not set yet"); return _table_base_offset; }
void emit(CodeBuffer& cb);
// Returns the offset of the last entry (the top) of the constant table.
int top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); }
void calculate_offsets_and_size();
int find_offset(Constant& con) const;
void add(Constant& con);
Constant add(MachConstantNode* n, BasicType type, jvalue value);
Constant add(Metadata* metadata);
Constant add(MachConstantNode* n, MachOper* oper);
Constant add(MachConstantNode* n, jint i) {
jvalue value; value.i = i;
return add(n, T_INT, value);
}
Constant add(MachConstantNode* n, jlong j) {
jvalue value; value.j = j;
return add(n, T_LONG, value);
}
Constant add(MachConstantNode* n, jfloat f) {
jvalue value; value.f = f;
return add(n, T_FLOAT, value);
}
Constant add(MachConstantNode* n, jdouble d) {
jvalue value; value.d = d;
return add(n, T_DOUBLE, value);
}
// Jump-table
Constant add_jump_table(MachConstantNode* n);
void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
};
private: private:
// Fixed parameters to this compilation. // Fixed parameters to this compilation.
const int _compile_id; const int _compile_id;
@ -376,9 +260,6 @@ class Compile : public Phase {
int _fixed_slots; // count of frame slots not allocated by the register int _fixed_slots; // count of frame slots not allocated by the register
// allocator i.e. locks, original deopt pc, etc. // allocator i.e. locks, original deopt pc, etc.
uintx _max_node_limit; // Max unique node count during a single compilation. uintx _max_node_limit; // Max unique node count during a single compilation.
// For deopt
int _orig_pc_slot;
int _orig_pc_slot_offset_in_bytes;
int _major_progress; // Count of something big happening int _major_progress; // Count of something big happening
bool _inlining_progress; // progress doing incremental inlining? bool _inlining_progress; // progress doing incremental inlining?
@ -457,7 +338,6 @@ class Compile : public Phase {
Node* _recent_alloc_ctl; Node* _recent_alloc_ctl;
// Constant table // Constant table
ConstantTable _constant_table; // The constant table for this compile.
MachConstantBaseNode* _mach_constant_base_node; // Constant table base node singleton. MachConstantBaseNode* _mach_constant_base_node; // Constant table base node singleton.
@ -586,27 +466,12 @@ class Compile : public Phase {
int _inner_loops; // Number of inner loops in the method int _inner_loops; // Number of inner loops in the method
Matcher* _matcher; // Engine to map ideal to machine instructions Matcher* _matcher; // Engine to map ideal to machine instructions
PhaseRegAlloc* _regalloc; // Results of register allocation. PhaseRegAlloc* _regalloc; // Results of register allocation.
int _frame_slots; // Size of total frame in stack slots
CodeOffsets _code_offsets; // Offsets into the code for various interesting entries
RegMask _FIRST_STACK_mask; // All stack slots usable for spills (depends on frame layout) RegMask _FIRST_STACK_mask; // All stack slots usable for spills (depends on frame layout)
Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin
void* _indexSet_free_block_list; // free list of IndexSet bit blocks void* _indexSet_free_block_list; // free list of IndexSet bit blocks
int _interpreter_frame_size; int _interpreter_frame_size;
uint _node_bundling_limit; PhaseOutput* _output;
Bundle* _node_bundling_base; // Information for instruction bundling
// Instruction bits passed off to the VM
int _method_size; // Size of nmethod code segment in bytes
CodeBuffer _code_buffer; // Where the code is assembled
int _first_block_size; // Size of unvalidated entry point code / OSR poison code
ExceptionHandlerTable _handler_table; // Table of native-code exception handlers
ImplicitExceptionTable _inc_table; // Table of implicit null checks in native code
OopMapSet* _oop_map_set; // Table of oop maps (one for each safepoint location)
BufferBlob* _scratch_buffer_blob; // For temporary code buffers.
relocInfo* _scratch_locs_memory; // For temporary code buffers.
int _scratch_const_size; // For temporary code buffers.
bool _in_scratch_emit_size; // true when in scratch_emit_size.
void reshape_address(AddPNode* n); void reshape_address(AddPNode* n);
@ -618,6 +483,11 @@ class Compile : public Phase {
return (Compile*) ciEnv::current()->compiler_data(); return (Compile*) ciEnv::current()->compiler_data();
} }
int interpreter_frame_size() const { return _interpreter_frame_size; }
PhaseOutput* output() const { return _output; }
void set_output(PhaseOutput* o) { _output = o; }
// ID for this compilation. Useful for setting breakpoints in the debugger. // ID for this compilation. Useful for setting breakpoints in the debugger.
int compile_id() const { return _compile_id; } int compile_id() const { return _compile_id; }
DirectiveSet* directive() const { return _directive; } DirectiveSet* directive() const { return _directive; }
@ -646,6 +516,7 @@ class Compile : public Phase {
address stub_function() const { return _stub_function; } address stub_function() const { return _stub_function; }
const char* stub_name() const { return _stub_name; } const char* stub_name() const { return _stub_name; }
address stub_entry_point() const { return _stub_entry_point; } address stub_entry_point() const { return _stub_entry_point; }
void set_stub_entry_point(address z) { _stub_entry_point = z; }
// Control of this compilation. // Control of this compilation.
int fixed_slots() const { assert(_fixed_slots >= 0, ""); return _fixed_slots; } int fixed_slots() const { assert(_fixed_slots >= 0, ""); return _fixed_slots; }
@ -936,9 +807,6 @@ class Compile : public Phase {
void remove_modified_node(Node* n) NOT_DEBUG_RETURN; void remove_modified_node(Node* n) NOT_DEBUG_RETURN;
DEBUG_ONLY( Unique_Node_List* modified_nodes() const { return _modified_nodes; } ) DEBUG_ONLY( Unique_Node_List* modified_nodes() const { return _modified_nodes; } )
// Constant table
ConstantTable& constant_table() { return _constant_table; }
MachConstantBaseNode* mach_constant_base_node(); MachConstantBaseNode* mach_constant_base_node();
bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; } bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
// Generated by adlc, true if CallNode requires MachConstantBase. // Generated by adlc, true if CallNode requires MachConstantBase.
@ -1124,26 +992,16 @@ class Compile : public Phase {
int inner_loops() const { return _inner_loops; } int inner_loops() const { return _inner_loops; }
Matcher* matcher() { return _matcher; } Matcher* matcher() { return _matcher; }
PhaseRegAlloc* regalloc() { return _regalloc; } PhaseRegAlloc* regalloc() { return _regalloc; }
int frame_slots() const { return _frame_slots; }
int frame_size_in_words() const; // frame_slots in units of the polymorphic 'words'
int frame_size_in_bytes() const { return _frame_slots << LogBytesPerInt; }
RegMask& FIRST_STACK_mask() { return _FIRST_STACK_mask; } RegMask& FIRST_STACK_mask() { return _FIRST_STACK_mask; }
Arena* indexSet_arena() { return _indexSet_arena; } Arena* indexSet_arena() { return _indexSet_arena; }
void* indexSet_free_block_list() { return _indexSet_free_block_list; } void* indexSet_free_block_list() { return _indexSet_free_block_list; }
uint node_bundling_limit() { return _node_bundling_limit; } DebugInformationRecorder* debug_info() { return env()->debug_info(); }
Bundle* node_bundling_base() { return _node_bundling_base; }
void set_node_bundling_limit(uint n) { _node_bundling_limit = n; }
void set_node_bundling_base(Bundle* b) { _node_bundling_base = b; }
bool starts_bundle(const Node *n) const;
bool need_stack_bang(int frame_size_in_bytes) const;
bool need_register_stack_bang() const;
void update_interpreter_frame_size(int size) { void update_interpreter_frame_size(int size) {
if (_interpreter_frame_size < size) { if (_interpreter_frame_size < size) {
_interpreter_frame_size = size; _interpreter_frame_size = size;
} }
} }
int bang_size_in_bytes() const;
void set_matcher(Matcher* m) { _matcher = m; } void set_matcher(Matcher* m) { _matcher = m; }
//void set_regalloc(PhaseRegAlloc* ra) { _regalloc = ra; } //void set_regalloc(PhaseRegAlloc* ra) { _regalloc = ra; }
@ -1153,40 +1011,13 @@ class Compile : public Phase {
void set_java_calls(int z) { _java_calls = z; } void set_java_calls(int z) { _java_calls = z; }
void set_inner_loops(int z) { _inner_loops = z; } void set_inner_loops(int z) { _inner_loops = z; }
// Instruction bits passed off to the VM
int code_size() { return _method_size; }
CodeBuffer* code_buffer() { return &_code_buffer; }
int first_block_size() { return _first_block_size; }
void set_frame_complete(int off) { if (!in_scratch_emit_size()) { _code_offsets.set_value(CodeOffsets::Frame_Complete, off); } }
ExceptionHandlerTable* handler_table() { return &_handler_table; }
ImplicitExceptionTable* inc_table() { return &_inc_table; }
OopMapSet* oop_map_set() { return _oop_map_set; }
DebugInformationRecorder* debug_info() { return env()->debug_info(); }
Dependencies* dependencies() { return env()->dependencies(); } Dependencies* dependencies() { return env()->dependencies(); }
BufferBlob* scratch_buffer_blob() { return _scratch_buffer_blob; }
void init_scratch_buffer_blob(int const_size);
void clear_scratch_buffer_blob();
void set_scratch_buffer_blob(BufferBlob* b) { _scratch_buffer_blob = b; }
relocInfo* scratch_locs_memory() { return _scratch_locs_memory; }
void set_scratch_locs_memory(relocInfo* b) { _scratch_locs_memory = b; }
// emit to scratch blob, report resulting size
uint scratch_emit_size(const Node* n);
void set_in_scratch_emit_size(bool x) { _in_scratch_emit_size = x; }
bool in_scratch_emit_size() const { return _in_scratch_emit_size; }
enum ScratchBufferBlob {
MAX_inst_size = 2048,
MAX_locs_size = 128, // number of relocInfo elements
MAX_const_size = 128,
MAX_stubs_size = 128
};
// Major entry point. Given a Scope, compile the associated method. // Major entry point. Given a Scope, compile the associated method.
// For normal compilations, entry_bci is InvocationEntryBci. For on stack // For normal compilations, entry_bci is InvocationEntryBci. For on stack
// replacement, entry_bci indicates the bytecode for which to compile a // replacement, entry_bci indicates the bytecode for which to compile a
// continuation. // continuation.
Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, Compile(ciEnv* ci_env, ciMethod* target,
int entry_bci, bool subsume_loads, bool do_escape_analysis, int entry_bci, bool subsume_loads, bool do_escape_analysis,
bool eliminate_boxing, DirectiveSet* directive); bool eliminate_boxing, DirectiveSet* directive);
@ -1221,67 +1052,8 @@ class Compile : public Phase {
// returns true if adr overlaps with the given alias category // returns true if adr overlaps with the given alias category
bool can_alias(const TypePtr* adr, int alias_idx); bool can_alias(const TypePtr* adr, int alias_idx);
// Driver for converting compiler's IR into machine code bits
void Output();
// Accessors for node bundling info.
Bundle* node_bundling(const Node *n);
bool valid_bundle_info(const Node *n);
// Schedule and Bundle the instructions
void ScheduleAndBundle();
// Build OopMaps for each GC point
void BuildOopMaps();
// Append debug info for the node "local" at safepoint node "sfpt" to the
// "array", May also consult and add to "objs", which describes the
// scalar-replaced objects.
void FillLocArray( int idx, MachSafePointNode* sfpt,
Node *local, GrowableArray<ScopeValue*> *array,
GrowableArray<ScopeValue*> *objs );
// If "objs" contains an ObjectValue whose id is "id", returns it, else NULL. // If "objs" contains an ObjectValue whose id is "id", returns it, else NULL.
static ObjectValue* sv_for_node_id(GrowableArray<ScopeValue*> *objs, int id); static ObjectValue* sv_for_node_id(GrowableArray<ScopeValue*> *objs, int id);
// Requres that "objs" does not contains an ObjectValue whose id matches
// that of "sv. Appends "sv".
static void set_sv_for_object_node(GrowableArray<ScopeValue*> *objs,
ObjectValue* sv );
// Process an OopMap Element while emitting nodes
void Process_OopMap_Node(MachNode *mach, int code_offset);
class BufferSizingData {
public:
int _stub;
int _code;
int _const;
int _reloc;
BufferSizingData() :
_stub(0),
_code(0),
_const(0),
_reloc(0)
{ };
};
// Initialize code buffer
void estimate_buffer_size(int& const_req);
CodeBuffer* init_buffer(BufferSizingData& buf_sizes);
// Write out basic block data to code buffer
void fill_buffer(CodeBuffer* cb, uint* blk_starts);
// Determine which variable sized branches can be shortened
void shorten_branches(uint* blk_starts, BufferSizingData& buf_sizes);
// Compute the size of first NumberOfLoopInstrToAlign instructions
// at the head of a loop.
void compute_loop_first_inst_sizes();
// Compute the information for the exception tables
void FillExceptionTables(uint cnt, uint *call_returns, uint *inct_starts, Label *blk_labels);
// Stack slots that may be unused by the calling convention but must // Stack slots that may be unused by the calling convention but must
// otherwise be preserved. On Intel this includes the return address. // otherwise be preserved. On Intel this includes the return address.
@ -1364,16 +1136,6 @@ class Compile : public Phase {
// End-of-run dumps. // End-of-run dumps.
static void print_statistics() PRODUCT_RETURN; static void print_statistics() PRODUCT_RETURN;
// Dump formatted assembly
#if defined(SUPPORT_OPTO_ASSEMBLY)
void dump_asm_on(outputStream* ost, int* pcs, uint pc_limit);
void dump_asm(int* pcs = NULL, uint pc_limit = 0) { dump_asm_on(tty, pcs, pc_limit); }
#else
void dump_asm_on(outputStream* ost, int* pcs, uint pc_limit) { return; }
void dump_asm(int* pcs = NULL, uint pc_limit = 0) { return; }
#endif
void dump_pc(int *pcs, int pc_limit, Node *n);
// Verify ADLC assumptions during startup // Verify ADLC assumptions during startup
static void adlc_verification() PRODUCT_RETURN; static void adlc_verification() PRODUCT_RETURN;

View file

@ -0,0 +1,246 @@
/*
* Copyright (c) 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
#include "opto/block.hpp"
#include "opto/constantTable.hpp"
#include "opto/machnode.hpp"
#include "opto/output.hpp"
//=============================================================================
// Two Constant's are equal when the type and the value are equal.
bool ConstantTable::Constant::operator==(const Constant& other) {
if (type() != other.type() ) return false;
if (can_be_reused() != other.can_be_reused()) return false;
// For floating point values we compare the bit pattern.
switch (type()) {
case T_INT:
case T_FLOAT: return (_v._value.i == other._v._value.i);
case T_LONG:
case T_DOUBLE: return (_v._value.j == other._v._value.j);
case T_OBJECT:
case T_ADDRESS: return (_v._value.l == other._v._value.l);
case T_VOID: return (_v._value.l == other._v._value.l); // jump-table entries
case T_METADATA: return (_v._metadata == other._v._metadata);
default: ShouldNotReachHere(); return false;
}
}
int ConstantTable::qsort_comparator(Constant* a, Constant* b) {
// sort descending
if (a->freq() > b->freq()) return -1;
if (a->freq() < b->freq()) return 1;
return 0;
}
static int type_to_size_in_bytes(BasicType t) {
switch (t) {
case T_INT: return sizeof(jint );
case T_LONG: return sizeof(jlong );
case T_FLOAT: return sizeof(jfloat );
case T_DOUBLE: return sizeof(jdouble);
case T_METADATA: return sizeof(Metadata*);
// We use T_VOID as marker for jump-table entries (labels) which
// need an internal word relocation.
case T_VOID:
case T_ADDRESS:
case T_OBJECT: return sizeof(jobject);
default:
ShouldNotReachHere();
return -1;
}
}
void ConstantTable::calculate_offsets_and_size() {
// First, sort the array by frequencies.
_constants.sort(qsort_comparator);
#ifdef ASSERT
// Make sure all jump-table entries were sorted to the end of the
// array (they have a negative frequency).
bool found_void = false;
for (int i = 0; i < _constants.length(); i++) {
Constant con = _constants.at(i);
if (con.type() == T_VOID)
found_void = true; // jump-tables
else
assert(!found_void, "wrong sorting");
}
#endif
int offset = 0;
for (int i = 0; i < _constants.length(); i++) {
Constant* con = _constants.adr_at(i);
// Align offset for type.
int typesize = type_to_size_in_bytes(con->type());
offset = align_up(offset, typesize);
con->set_offset(offset); // set constant's offset
if (con->type() == T_VOID) {
MachConstantNode* n = (MachConstantNode*) con->get_jobject();
offset = offset + typesize * n->outcnt(); // expand jump-table
} else {
offset = offset + typesize;
}
}
// Align size up to the next section start (which is insts; see
// CodeBuffer::align_at_start).
assert(_size == -1, "already set?");
_size = align_up(offset, (int)CodeEntryAlignment);
}
void ConstantTable::emit(CodeBuffer& cb) {
MacroAssembler _masm(&cb);
for (int i = 0; i < _constants.length(); i++) {
Constant con = _constants.at(i);
address constant_addr = NULL;
switch (con.type()) {
case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break;
case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break;
case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break;
case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
case T_OBJECT: {
jobject obj = con.get_jobject();
int oop_index = _masm.oop_recorder()->find_index(obj);
constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
break;
}
case T_ADDRESS: {
address addr = (address) con.get_jobject();
constant_addr = _masm.address_constant(addr);
break;
}
// We use T_VOID as marker for jump-table entries (labels) which
// need an internal word relocation.
case T_VOID: {
MachConstantNode* n = (MachConstantNode*) con.get_jobject();
// Fill the jump-table with a dummy word. The real value is
// filled in later in fill_jump_table.
address dummy = (address) n;
constant_addr = _masm.address_constant(dummy);
// Expand jump-table
for (uint i = 1; i < n->outcnt(); i++) {
address temp_addr = _masm.address_constant(dummy + i);
assert(temp_addr, "consts section too small");
}
break;
}
case T_METADATA: {
Metadata* obj = con.get_metadata();
int metadata_index = _masm.oop_recorder()->find_index(obj);
constant_addr = _masm.address_constant((address) obj, metadata_Relocation::spec(metadata_index));
break;
}
default: ShouldNotReachHere();
}
assert(constant_addr, "consts section too small");
assert((constant_addr - _masm.code()->consts()->start()) == con.offset(),
"must be: %d == %d", (int) (constant_addr - _masm.code()->consts()->start()), (int)(con.offset()));
}
}
int ConstantTable::find_offset(Constant& con) const {
int idx = _constants.find(con);
guarantee(idx != -1, "constant must be in constant table");
int offset = _constants.at(idx).offset();
guarantee(offset != -1, "constant table not emitted yet?");
return offset;
}
void ConstantTable::add(Constant& con) {
if (con.can_be_reused()) {
int idx = _constants.find(con);
if (idx != -1 && _constants.at(idx).can_be_reused()) {
_constants.adr_at(idx)->inc_freq(con.freq()); // increase the frequency by the current value
return;
}
}
(void) _constants.append(con);
}
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
Block* b = Compile::current()->cfg()->get_block_for_node(n);
Constant con(type, value, b->_freq);
add(con);
return con;
}
ConstantTable::Constant ConstantTable::add(Metadata* metadata) {
Constant con(metadata);
add(con);
return con;
}
ConstantTable::Constant ConstantTable::add(MachConstantNode* n, MachOper* oper) {
jvalue value;
BasicType type = oper->type()->basic_type();
switch (type) {
case T_LONG: value.j = oper->constantL(); break;
case T_FLOAT: value.f = oper->constantF(); break;
case T_DOUBLE: value.d = oper->constantD(); break;
case T_OBJECT:
case T_ADDRESS: value.l = (jobject) oper->constant(); break;
case T_METADATA: return add((Metadata*)oper->constant()); break;
default: guarantee(false, "unhandled type: %s", type2name(type));
}
return add(n, type, value);
}
ConstantTable::Constant ConstantTable::add_jump_table(MachConstantNode* n) {
jvalue value;
// We can use the node pointer here to identify the right jump-table
// as this method is called from Compile::Fill_buffer right before
// the MachNodes are emitted and the jump-table is filled (means the
// MachNode pointers do not change anymore).
value.l = (jobject) n;
Constant con(T_VOID, value, next_jump_table_freq(), false); // Labels of a jump-table cannot be reused.
add(con);
return con;
}
void ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {
// If called from Compile::scratch_emit_size do nothing.
if (Compile::current()->output()->in_scratch_emit_size()) return;
assert(labels.is_nonempty(), "must be");
assert((uint) labels.length() == n->outcnt(), "must be equal: %d == %d", labels.length(), n->outcnt());
// Since MachConstantNode::constant_offset() also contains
// table_base_offset() we need to subtract the table_base_offset()
// to get the plain offset into the constant table.
int offset = n->constant_offset() - table_base_offset();
MacroAssembler _masm(&cb);
address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
for (uint i = 0; i < n->outcnt(); i++) {
address* constant_addr = &jump_table_base[i];
assert(*constant_addr == (((address) n) + i), "all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, p2i(*constant_addr), p2i(((address) n) + i));
*constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
}
}

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_OPTO_CONSTANTTABLE_HPP
#define SHARE_OPTO_CONSTANTTABLE_HPP
#include "utilities/globalDefinitions.hpp"
class CodeBuffer;
class Metadata;
class MachConstantNode;
class MachOper;
class ConstantTable {
public:
// Constant entry of the constant table.
class Constant {
private:
BasicType _type;
union {
jvalue _value;
Metadata* _metadata;
} _v;
int _offset; // offset of this constant (in bytes) relative to the constant table base.
float _freq;
bool _can_be_reused; // true (default) if the value can be shared with other users.
public:
Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; }
Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) :
_type(type),
_offset(-1),
_freq(freq),
_can_be_reused(can_be_reused)
{
assert(type != T_METADATA, "wrong constructor");
_v._value = value;
}
Constant(Metadata* metadata, bool can_be_reused = true) :
_type(T_METADATA),
_offset(-1),
_freq(0.0f),
_can_be_reused(can_be_reused)
{
_v._metadata = metadata;
}
bool operator==(const Constant& other);
BasicType type() const { return _type; }
jint get_jint() const { return _v._value.i; }
jlong get_jlong() const { return _v._value.j; }
jfloat get_jfloat() const { return _v._value.f; }
jdouble get_jdouble() const { return _v._value.d; }
jobject get_jobject() const { return _v._value.l; }
Metadata* get_metadata() const { return _v._metadata; }
int offset() const { return _offset; }
void set_offset(int offset) { _offset = offset; }
float freq() const { return _freq; }
void inc_freq(float freq) { _freq += freq; }
bool can_be_reused() const { return _can_be_reused; }
};
private:
GrowableArray<Constant> _constants; // Constants of this table.
int _size; // Size in bytes the emitted constant table takes (including padding).
int _table_base_offset; // Offset of the table base that gets added to the constant offsets.
int _nof_jump_tables; // Number of jump-tables in this constant table.
static int qsort_comparator(Constant* a, Constant* b);
// We use negative frequencies to keep the order of the
// jump-tables in which they were added. Otherwise we get into
// trouble with relocation.
float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); }
public:
ConstantTable() :
_size(-1),
_table_base_offset(-1), // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
_nof_jump_tables(0)
{}
int size() const { assert(_size != -1, "not calculated yet"); return _size; }
int calculate_table_base_offset() const; // AD specific
void set_table_base_offset(int x) { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; }
int table_base_offset() const { assert(_table_base_offset != -1, "not set yet"); return _table_base_offset; }
void emit(CodeBuffer& cb);
// Returns the offset of the last entry (the top) of the constant table.
int top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); }
void calculate_offsets_and_size();
int find_offset(Constant& con) const;
void add(Constant& con);
Constant add(MachConstantNode* n, BasicType type, jvalue value);
Constant add(Metadata* metadata);
Constant add(MachConstantNode* n, MachOper* oper);
Constant add(MachConstantNode* n, jint i) {
jvalue value; value.i = i;
return add(n, T_INT, value);
}
Constant add(MachConstantNode* n, jlong j) {
jvalue value; value.j = j;
return add(n, T_LONG, value);
}
Constant add(MachConstantNode* n, jfloat f) {
jvalue value; value.f = f;
return add(n, T_FLOAT, value);
}
Constant add(MachConstantNode* n, jdouble d) {
jvalue value; value.d = d;
return add(n, T_DOUBLE, value);
}
// Jump-table
Constant add_jump_table(MachConstantNode* n);
void fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
};
#endif // SHARE_OPTO_CONSTANTTABLE_HPP

View file

@ -27,6 +27,7 @@
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/compressedOops.hpp" #include "oops/compressedOops.hpp"
#include "opto/machnode.hpp" #include "opto/machnode.hpp"
#include "opto/output.hpp"
#include "opto/regalloc.hpp" #include "opto/regalloc.hpp"
#include "utilities/vmError.hpp" #include "utilities/vmError.hpp"
@ -154,7 +155,7 @@ uint MachNode::size(PhaseRegAlloc *ra_) const {
uint MachNode::emit_size(PhaseRegAlloc *ra_) const { uint MachNode::emit_size(PhaseRegAlloc *ra_) const {
// Emit into a trash buffer and count bytes emitted. // Emit into a trash buffer and count bytes emitted.
assert(ra_ == ra_->C->regalloc(), "sanity"); assert(ra_ == ra_->C->regalloc(), "sanity");
return ra_->C->scratch_emit_size(this); return ra_->C->output()->scratch_emit_size(this);
} }
@ -541,13 +542,13 @@ void MachTypeNode::dump_spec(outputStream *st) const {
int MachConstantNode::constant_offset() { int MachConstantNode::constant_offset() {
// Bind the offset lazily. // Bind the offset lazily.
if (_constant.offset() == -1) { if (_constant.offset() == -1) {
Compile::ConstantTable& constant_table = Compile::current()->constant_table(); ConstantTable& constant_table = Compile::current()->output()->constant_table();
int offset = constant_table.find_offset(_constant); int offset = constant_table.find_offset(_constant);
// If called from Compile::scratch_emit_size return the // If called from Compile::scratch_emit_size return the
// pre-calculated offset. // pre-calculated offset.
// NOTE: If the AD file does some table base offset optimizations // NOTE: If the AD file does some table base offset optimizations
// later the AD file needs to take care of this fact. // later the AD file needs to take care of this fact.
if (Compile::current()->in_scratch_emit_size()) { if (Compile::current()->output()->in_scratch_emit_size()) {
return constant_table.calculate_table_base_offset() + offset; return constant_table.calculate_table_base_offset() + offset;
} }
_constant.set_offset(constant_table.table_base_offset() + offset); _constant.set_offset(constant_table.table_base_offset() + offset);

View file

@ -26,6 +26,7 @@
#define SHARE_OPTO_MACHNODE_HPP #define SHARE_OPTO_MACHNODE_HPP
#include "opto/callnode.hpp" #include "opto/callnode.hpp"
#include "opto/constantTable.hpp"
#include "opto/matcher.hpp" #include "opto/matcher.hpp"
#include "opto/multnode.hpp" #include "opto/multnode.hpp"
#include "opto/node.hpp" #include "opto/node.hpp"
@ -447,7 +448,7 @@ public:
// Machine node that holds a constant which is stored in the constant table. // Machine node that holds a constant which is stored in the constant table.
class MachConstantNode : public MachTypeNode { class MachConstantNode : public MachTypeNode {
protected: protected:
Compile::Constant _constant; // This node's constant. ConstantTable::Constant _constant; // This node's constant.
public: public:
MachConstantNode() : MachTypeNode() { MachConstantNode() : MachTypeNode() {

File diff suppressed because it is too large Load diff

View file

@ -26,20 +26,24 @@
#define SHARE_OPTO_OUTPUT_HPP #define SHARE_OPTO_OUTPUT_HPP
#include "opto/ad.hpp" #include "opto/ad.hpp"
#include "opto/block.hpp" #include "opto/constantTable.hpp"
#include "opto/node.hpp" #include "opto/phase.hpp"
#include "code/debugInfo.hpp"
#include "code/exceptionHandlerTable.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
class AbstractCompiler;
class Arena; class Arena;
class Bundle; class Bundle;
class Block; class Block;
class Block_Array; class Block_Array;
class ciMethod;
class Compile;
class MachNode;
class MachSafePointNode;
class Node; class Node;
class Node_Array;
class Node_List;
class PhaseCFG; class PhaseCFG;
class PhaseChaitin;
class Pipeline_Use_Element;
class Pipeline_Use;
#ifndef PRODUCT #ifndef PRODUCT
#define DEBUG_ARG(x) , x #define DEBUG_ARG(x) , x
#else #else
@ -51,167 +55,157 @@ enum {
initial_const_capacity = 4 * 1024 initial_const_capacity = 4 * 1024
}; };
//------------------------------Scheduling---------------------------------- class BufferSizingData {
// This class contains all the information necessary to implement instruction public:
// scheduling and bundling. int _stub;
class Scheduling { int _code;
int _const;
int _reloc;
BufferSizingData() :
_stub(0),
_code(0),
_const(0),
_reloc(0)
{ };
};
class PhaseOutput : public Phase {
private: private:
// Arena to use // Instruction bits passed off to the VM
Arena *_arena; int _method_size; // Size of nmethod code segment in bytes
CodeBuffer _code_buffer; // Where the code is assembled
int _first_block_size; // Size of unvalidated entry point code / OSR poison code
ExceptionHandlerTable _handler_table; // Table of native-code exception handlers
ImplicitExceptionTable _inc_table; // Table of implicit null checks in native code
OopMapSet* _oop_map_set; // Table of oop maps (one for each safepoint location)
BufferBlob* _scratch_buffer_blob; // For temporary code buffers.
relocInfo* _scratch_locs_memory; // For temporary code buffers.
int _scratch_const_size; // For temporary code buffers.
bool _in_scratch_emit_size; // true when in scratch_emit_size.
// Control-Flow Graph info int _frame_slots; // Size of total frame in stack slots
PhaseCFG *_cfg; CodeOffsets _code_offsets; // Offsets into the code for various interesting entries
// Register Allocation info
PhaseRegAlloc *_regalloc;
// Number of nodes in the method
uint _node_bundling_limit; uint _node_bundling_limit;
Bundle* _node_bundling_base; // Information for instruction bundling
// List of scheduled nodes. Generated in reverse order // For deopt
Node_List _scheduled; int _orig_pc_slot;
int _orig_pc_slot_offset_in_bytes;
// List of nodes currently available for choosing for scheduling ConstantTable _constant_table; // The constant table for this compilation unit.
Node_List _available;
// For each instruction beginning a bundle, the number of following
// nodes to be bundled with it.
Bundle *_node_bundling_base;
// Mapping from register to Node
Node_List _reg_node;
// Free list for pinch nodes.
Node_List _pinch_free_list;
// Latency from the beginning of the containing basic block (base 1)
// for each node.
unsigned short *_node_latency;
// Number of uses of this node within the containing basic block.
short *_uses;
// Schedulable portion of current block. Skips Region/Phi/CreateEx up
// front, branch+proj at end. Also skips Catch/CProj (same as
// branch-at-end), plus just-prior exception-throwing call.
uint _bb_start, _bb_end;
// Latency from the end of the basic block as scheduled
unsigned short *_current_latency;
// Remember the next node
Node *_next_node;
// Use this for an unconditional branch delay slot
Node *_unconditional_delay_slot;
// Pointer to a Nop
MachNopNode *_nop;
// Length of the current bundle, in instructions
uint _bundle_instr_count;
// Current Cycle number, for computing latencies and bundling
uint _bundle_cycle_number;
// Bundle information
Pipeline_Use_Element _bundle_use_elements[resource_count];
Pipeline_Use _bundle_use;
// Dump the available list
void dump_available() const;
public: public:
Scheduling(Arena *arena, Compile &compile); PhaseOutput();
~PhaseOutput();
// Destructor // Convert Nodes to instruction bits and pass off to the VM
NOT_PRODUCT( ~Scheduling(); ) void Output();
bool need_stack_bang(int frame_size_in_bytes) const;
bool need_register_stack_bang() const;
void compute_loop_first_inst_sizes();
// Step ahead "i" cycles void install_code(ciMethod* target,
void step(uint i); int entry_bci,
AbstractCompiler* compiler,
bool has_unsafe_access,
bool has_wide_vectors,
RTMState rtm_state);
// Step ahead 1 cycle, and clear the bundle state (for example, void install_stub(const char* stub_name,
// at a branch target) bool caller_must_gc_arguments);
void step_and_clear();
Bundle* node_bundling(const Node *n) { // Constant table
assert(valid_bundle_info(n), "oob"); ConstantTable& constant_table() { return _constant_table; }
return (&_node_bundling_base[n->_idx]);
}
bool valid_bundle_info(const Node *n) const { // The architecture description provides short branch variants for some long
return (_node_bundling_limit > n->_idx); // branch instructions. Replace eligible long branches with short branches.
} void shorten_branches(uint* blk_starts, BufferSizingData& buf_sizes);
ObjectValue* sv_for_node_id(GrowableArray<ScopeValue*> *objs, int id);
void set_sv_for_object_node(GrowableArray<ScopeValue*> *objs, ObjectValue* sv);
void FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
GrowableArray<ScopeValue*> *array,
GrowableArray<ScopeValue*> *objs );
bool starts_bundle(const Node *n) const { void Process_OopMap_Node(MachNode *mach, int current_offset);
return (_node_bundling_limit > n->_idx && _node_bundling_base[n->_idx].starts_bundle());
}
// Do the scheduling // Initialize code buffer
void DoScheduling(); void estimate_buffer_size(int& const_req);
CodeBuffer* init_buffer(BufferSizingData& buf_sizes);
// Compute the local latencies walking forward over the list of // Write out basic block data to code buffer
// nodes for a basic block void fill_buffer(CodeBuffer* cb, uint* blk_starts);
void ComputeLocalLatenciesForward(const Block *bb);
// Compute the register antidependencies within a basic block // Compute the information for the exception tables
void ComputeRegisterAntidependencies(Block *bb); void FillExceptionTables(uint cnt, uint *call_returns, uint *inct_starts, Label *blk_labels);
void verify_do_def( Node *n, OptoReg::Name def, const char *msg );
void verify_good_schedule( Block *b, const char *msg );
void anti_do_def( Block *b, Node *def, OptoReg::Name def_reg, int is_def );
void anti_do_use( Block *b, Node *use, OptoReg::Name use_reg );
// Add a node to the current bundle // Perform instruction scheduling and bundling over the sequence of
void AddNodeToBundle(Node *n, const Block *bb); // instructions in backwards order.
void ScheduleAndBundle();
// Add a node to the list of available nodes void install();
void AddNodeToAvailableList(Node *n);
// Compute the local use count for the nodes in a block, and compute // Instruction bits passed off to the VM
// the list of instructions with no uses in the block as available int code_size() { return _method_size; }
void ComputeUseCount(const Block *bb); CodeBuffer* code_buffer() { return &_code_buffer; }
int first_block_size() { return _first_block_size; }
void set_frame_complete(int off) { if (!in_scratch_emit_size()) { _code_offsets.set_value(CodeOffsets::Frame_Complete, off); } }
ExceptionHandlerTable* handler_table() { return &_handler_table; }
ImplicitExceptionTable* inc_table() { return &_inc_table; }
OopMapSet* oop_map_set() { return _oop_map_set; }
// Choose an instruction from the available list to add to the bundle // Scratch buffer
Node * ChooseNodeToBundle(); BufferBlob* scratch_buffer_blob() { return _scratch_buffer_blob; }
void init_scratch_buffer_blob(int const_size);
void clear_scratch_buffer_blob();
void set_scratch_buffer_blob(BufferBlob* b) { _scratch_buffer_blob = b; }
relocInfo* scratch_locs_memory() { return _scratch_locs_memory; }
void set_scratch_locs_memory(relocInfo* b) { _scratch_locs_memory = b; }
// See if this Node fits into the currently accumulating bundle // emit to scratch blob, report resulting size
bool NodeFitsInBundle(Node *n); uint scratch_emit_size(const Node* n);
void set_in_scratch_emit_size(bool x) { _in_scratch_emit_size = x; }
bool in_scratch_emit_size() const { return _in_scratch_emit_size; }
// Decrement the use count for a node enum ScratchBufferBlob {
void DecrementUseCounts(Node *n, const Block *bb); MAX_inst_size = 2048,
MAX_locs_size = 128, // number of relocInfo elements
MAX_const_size = 128,
MAX_stubs_size = 128
};
// Garbage collect pinch nodes for reuse by other blocks. int frame_slots() const { return _frame_slots; }
void garbage_collect_pinch_nodes(); int frame_size_in_words() const; // frame_slots in units of the polymorphic 'words'
// Clean up a pinch node for reuse (helper for above). int frame_size_in_bytes() const { return _frame_slots << LogBytesPerInt; }
void cleanup_pinch( Node *pinch );
// Information for statistics gathering int bang_size_in_bytes() const;
#ifndef PRODUCT
private:
// Gather information on size of nops relative to total
uint _branches, _unconditional_delays;
static uint _total_nop_size, _total_method_size; uint node_bundling_limit();
static uint _total_branches, _total_unconditional_delays; Bundle* node_bundling_base();
static uint _total_instructions_per_bundle[Pipeline::_max_instrs_per_cycle+1]; void set_node_bundling_limit(uint n) { _node_bundling_limit = n; }
void set_node_bundling_base(Bundle* b) { _node_bundling_base = b; }
public: Bundle* node_bundling(const Node *n);
static void print_statistics(); bool valid_bundle_info(const Node *n);
static void increment_instructions_per_bundle(uint i) { bool starts_bundle(const Node *n) const;
_total_instructions_per_bundle[i]++;
}
static void increment_nop_size(uint s) { // Dump formatted assembly
_total_nop_size += s; #if defined(SUPPORT_OPTO_ASSEMBLY)
} void dump_asm_on(outputStream* ost, int* pcs, uint pc_limit);
void dump_asm(int* pcs = NULL, uint pc_limit = 0) { dump_asm_on(tty, pcs, pc_limit); }
static void increment_method_size(uint s) { #else
_total_method_size += s; void dump_asm_on(outputStream* ost, int* pcs, uint pc_limit) { return; }
} void dump_asm(int* pcs = NULL, uint pc_limit = 0) { return; }
#endif #endif
// Build OopMaps for each GC point
void BuildOopMaps();
#ifndef PRODUCT
static void print_statistics();
#endif
}; };
#endif // SHARE_OPTO_OUTPUT_HPP #endif // SHARE_OPTO_OUTPUT_HPP

View file

@ -59,6 +59,7 @@ public:
Ideal_Loop, // Find idealized trip-counted loops Ideal_Loop, // Find idealized trip-counted loops
Macro_Expand, // Expand macro nodes Macro_Expand, // Expand macro nodes
Peephole, // Apply peephole optimizations Peephole, // Apply peephole optimizations
Output,
last_phase last_phase
}; };

View file

@ -58,6 +58,7 @@
#include "opto/matcher.hpp" #include "opto/matcher.hpp"
#include "opto/memnode.hpp" #include "opto/memnode.hpp"
#include "opto/mulnode.hpp" #include "opto/mulnode.hpp"
#include "opto/output.hpp"
#include "opto/runtime.hpp" #include "opto/runtime.hpp"
#include "opto/subnode.hpp" #include "opto/subnode.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"