mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 01:54:47 +02:00
8240363: Refactor Compile::Output() to its own Phase
Reviewed-by: kvn, vlivanov
This commit is contained in:
parent
6ddb0f2b2c
commit
21cd75cb98
28 changed files with 1388 additions and 1228 deletions
|
@ -1575,7 +1575,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
|||
//=============================================================================
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1602,9 +1602,9 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
|||
void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
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);
|
||||
|
||||
if (framesize < ((1 << 9) + 2 * wordSize)) {
|
||||
|
@ -1625,7 +1625,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
// 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");
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
if (C->need_stack_bang(bangsize) && UseStackBanging)
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
if (C->output()->need_stack_bang(bangsize) && UseStackBanging)
|
||||
__ generate_stack_overflow_check(bangsize);
|
||||
|
||||
__ build_frame(framesize);
|
||||
|
@ -1653,12 +1653,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
Unimplemented();
|
||||
}
|
||||
|
||||
C->set_frame_complete(cbuf.insts_size());
|
||||
C->output()->set_frame_complete(cbuf.insts_size());
|
||||
|
||||
if (C->has_mach_constant_base_node()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -1679,7 +1679,7 @@ int MachPrologNode::reloc() const
|
|||
#ifndef PRODUCT
|
||||
void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
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);
|
||||
|
||||
|
@ -1705,7 +1705,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
|||
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
int framesize = C->frame_slots() << LogBytesPerInt;
|
||||
int framesize = C->output()->frame_slots() << LogBytesPerInt;
|
||||
|
||||
__ remove_frame(framesize);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "opto/compile.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef PRODUCT
|
||||
|
@ -745,7 +746,7 @@ address MacroAssembler::trampoline_call(Address entry, CodeBuffer *cbuf) {
|
|||
CompileTask* task = ciEnv::current()->task();
|
||||
in_scratch_emit_size =
|
||||
(task != NULL && is_c2_compile(task->comp_level()) &&
|
||||
Compile::current()->in_scratch_emit_size());
|
||||
Compile::current()->output()->in_scratch_emit_size());
|
||||
#endif
|
||||
if (!in_scratch_emit_size) {
|
||||
address stub = emit_trampoline_stub(offset(), entry.target());
|
||||
|
|
|
@ -194,7 +194,7 @@ void emit_hi(CodeBuffer &cbuf, int val) { }
|
|||
//=============================================================================
|
||||
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);
|
||||
// flds, fldd: 8-bit offset multiplied by 4: +/- 1024
|
||||
// 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 {
|
||||
Compile* C = ra_->C;
|
||||
Compile::ConstantTable& constant_table = C->constant_table();
|
||||
ConstantTable& constant_table = C->output()->constant_table();
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
// Remove two words for return addr and rbp,
|
||||
framesize -= 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
|
||||
// stack. But the stack safety zone should account for that.
|
||||
// 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("PUSH R_FP|R_LR_LR"); st->print("\t");
|
||||
|
@ -275,9 +275,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
__ 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");
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
// Remove two words for return addr and fp,
|
||||
framesize -= 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
|
||||
// stack. But the stack safety zone should account for that.
|
||||
// See bugs 4446381, 4468289, 4497237.
|
||||
if (C->need_stack_bang(bangsize)) {
|
||||
if (C->output()->need_stack_bang(bangsize)) {
|
||||
__ 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
|
||||
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()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ int MachPrologNode::reloc() const {
|
|||
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
Compile* C = ra_->C;
|
||||
|
||||
size_t framesize = C->frame_size_in_bytes();
|
||||
size_t framesize = C->output()->frame_size_in_bytes();
|
||||
framesize -= 2*wordSize;
|
||||
|
||||
if (framesize != 0) {
|
||||
|
@ -342,7 +342,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
MacroAssembler _masm(&cbuf);
|
||||
Compile* C = ra_->C;
|
||||
|
||||
size_t framesize = C->frame_size_in_bytes();
|
||||
size_t framesize = C->output()->frame_size_in_bytes();
|
||||
framesize -= 2*wordSize;
|
||||
if (framesize != 0) {
|
||||
__ add_slow(SP, SP, framesize);
|
||||
|
@ -827,7 +827,7 @@ void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
|
||||
// BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
|
||||
assert(ra_ == ra_->C->regalloc(), "sanity");
|
||||
return ra_->C->scratch_emit_size(this);
|
||||
return ra_->C->output()->scratch_emit_size(this);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -1297,7 +1297,7 @@ static inline jlong replicate_immF(float con) {
|
|||
//=============================================================================
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1338,10 +1338,10 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
|||
#ifndef PRODUCT
|
||||
void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
Compile* C = ra_->C;
|
||||
const long framesize = C->frame_slots() << LogBytesPerInt;
|
||||
const long framesize = C->output()->frame_slots() << LogBytesPerInt;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1381,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
Compile* C = ra_->C;
|
||||
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");
|
||||
|
||||
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
|
||||
// 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");
|
||||
if (C->need_stack_bang(bangsize) && UseStackBanging) {
|
||||
if (C->output()->need_stack_bang(bangsize) && UseStackBanging) {
|
||||
// Unfortunately we cannot use the function provided in
|
||||
// assembler.cpp as we have to emulate the pipes. So I had to
|
||||
// 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;
|
||||
}
|
||||
// R11 trashed
|
||||
} // C->need_stack_bang(framesize) && UseStackBanging
|
||||
} // C->output()->need_stack_bang(framesize) && UseStackBanging
|
||||
|
||||
unsigned int bytes = (unsigned int)framesize;
|
||||
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);
|
||||
}
|
||||
|
||||
C->set_frame_complete(cbuf.insts_size());
|
||||
C->output()->set_frame_complete(cbuf.insts_size());
|
||||
}
|
||||
#undef ___
|
||||
#undef ___stop
|
||||
|
@ -1573,7 +1573,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
Compile* C = ra_->C;
|
||||
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?");
|
||||
|
||||
const bool method_needs_polling = do_polling() && C->is_method_compilation();
|
||||
|
@ -2786,7 +2786,7 @@ encode %{
|
|||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
if (!ra_->C->in_scratch_emit_size()) {
|
||||
if (!ra_->C->output()->in_scratch_emit_size()) {
|
||||
address const_toc_addr;
|
||||
// Create a non-oop constant, no relocation needed.
|
||||
// If it is an IC, it has a virtual_call_Relocation.
|
||||
|
@ -3053,7 +3053,7 @@ encode %{
|
|||
// TODO: PPC port $archOpcode(ppc64Opcode_addis);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
if (!ra_->C->in_scratch_emit_size()) {
|
||||
if (!ra_->C->output()->in_scratch_emit_size()) {
|
||||
intptr_t val = $src$$constant;
|
||||
relocInfo::relocType constant_reloc = $src->constant_reloc(); // src
|
||||
address const_toc_addr;
|
||||
|
@ -3791,7 +3791,7 @@ encode %{
|
|||
|
||||
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.
|
||||
const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method;
|
||||
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);
|
||||
ins_encode %{
|
||||
// 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);
|
||||
%}
|
||||
ins_pipe(pipe_class_memory);
|
||||
|
@ -6570,7 +6570,7 @@ instruct loadConP_lo(iRegPdst dst, immP_NM src, iRegLdst base) %{
|
|||
size(4);
|
||||
ins_encode %{
|
||||
// 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);
|
||||
%}
|
||||
ins_pipe(pipe_class_memory);
|
||||
|
|
|
@ -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.
|
||||
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) {
|
||||
return NULL; // CodeBuffer::expand failed.
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
int Compile::ConstantTable::calculate_table_base_offset() const {
|
||||
int ConstantTable::calculate_table_base_offset() const {
|
||||
return 0; // absolute addressing, no offset
|
||||
}
|
||||
|
||||
|
@ -840,15 +840,15 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
|||
st->print("\t");
|
||||
}
|
||||
|
||||
long framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
long framesize = C->output()->frame_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
|
||||
// Calls to C2R adapters often do not accept exceptional returns.
|
||||
// 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 stack. But the stack safety zone should
|
||||
// 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("push_frame %d", (int)-framesize);
|
||||
|
@ -862,8 +862,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
|
||||
__ verify_thread();
|
||||
|
||||
size_t framesize = C->frame_size_in_bytes();
|
||||
size_t bangsize = C->bang_size_in_bytes();
|
||||
size_t framesize = C->output()->frame_size_in_bytes();
|
||||
size_t bangsize = C->output()->bang_size_in_bytes();
|
||||
|
||||
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
|
||||
// use several kilobytes of stack. But the stack safety zone should
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -903,7 +903,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
if (C->has_mach_constant_base_node()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -940,7 +940,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
bool need_polling = do_polling() && C->is_method_compilation();
|
||||
|
||||
// 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);
|
||||
|
||||
if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
|
||||
|
@ -1257,7 +1257,7 @@ void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ra_) const {
|
|||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
int rem_space = 0;
|
||||
if (!(ra_->C->in_scratch_emit_size())) {
|
||||
if (!(ra_->C->output()->in_scratch_emit_size())) {
|
||||
rem_space = cbuf.insts()->remaining();
|
||||
if (rem_space <= _count*2 + 8) {
|
||||
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();
|
||||
}
|
||||
|
||||
if (!(ra_->C->in_scratch_emit_size())) {
|
||||
if (!(ra_->C->output()->in_scratch_emit_size())) {
|
||||
if (rem_space <= _count*2 + 8) {
|
||||
int rem_space2 = cbuf.insts()->remaining();
|
||||
tty->print_cr(", after = %d", rem_space2);
|
||||
|
|
|
@ -1002,7 +1002,7 @@ void emit_hi(CodeBuffer &cbuf, int val) { }
|
|||
//=============================================================================
|
||||
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) {
|
||||
// The table base offset might be less but then it fits into
|
||||
// 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 {
|
||||
Compile* C = ra_->C;
|
||||
Compile::ConstantTable& constant_table = C->constant_table();
|
||||
ConstantTable& constant_table = C->output()->constant_table();
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
size_t framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
size_t framesize = C->output()->frame_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
|
||||
// Calls to C2R adapters often do not accept exceptional returns.
|
||||
// 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
|
||||
// stack. But the stack safety zone should account for that.
|
||||
// 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");
|
||||
}
|
||||
|
||||
|
@ -1161,17 +1161,17 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
|
||||
__ 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%(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.
|
||||
// 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
|
||||
// stack. But the stack safety zone should account for that.
|
||||
// See bugs 4446381, 4468289, 4497237.
|
||||
if (C->need_stack_bang(bangsize)) {
|
||||
if (C->output()->need_stack_bang(bangsize)) {
|
||||
__ generate_stack_overflow_check(bangsize);
|
||||
}
|
||||
|
||||
|
@ -1182,12 +1182,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
__ add(G3, -framesize & 0x3ff, G3);
|
||||
__ save(SP, G3, SP);
|
||||
}
|
||||
C->set_frame_complete( __ offset() );
|
||||
C->output()->set_frame_complete( __ offset() );
|
||||
|
||||
if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -1570,7 +1570,7 @@ void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
|
||||
// BoxLockNode is not a MachNode, so we can't just call MachNode::size(ra_)
|
||||
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 %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
int framesize = ra_->C->frame_size_in_bytes();
|
||||
int framesize = ra_->C->output()->frame_size_in_bytes();
|
||||
Register temp_reg = G3;
|
||||
__ add(SP, framesize, temp_reg);
|
||||
__ cmp(temp_reg, FP);
|
||||
|
@ -8854,7 +8854,7 @@ instruct jumpXtnd(iRegX switch_val, o7RegI table) %{
|
|||
// zero offsets because they might change when
|
||||
// MachConstantBaseNode decides to optimize the constant table
|
||||
// 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;
|
||||
} else {
|
||||
table_reg = O7;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "opto/compile.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/regalloc.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
@ -126,7 +127,7 @@ IntelJccErratumAlignment::IntelJccErratumAlignment(MacroAssembler& masm, int jcc
|
|||
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.
|
||||
__ nop(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() {
|
||||
if (!VM_Version::has_intel_jcc_erratum() ||
|
||||
Compile::current()->in_scratch_emit_size()) {
|
||||
Compile::current()->output()->in_scratch_emit_size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -523,7 +523,7 @@ void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
|
|||
//=============================================================================
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -552,13 +552,13 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
|||
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
||||
Compile* C = ra_->C;
|
||||
|
||||
int framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int framesize = C->output()->frame_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
|
||||
// Remove wordSize for return addr which is already pushed.
|
||||
framesize -= wordSize;
|
||||
|
||||
if (C->need_stack_bang(bangsize)) {
|
||||
if (C->output()->need_stack_bang(bangsize)) {
|
||||
framesize -= wordSize;
|
||||
st->print("# stack bang (%d bytes)", bangsize);
|
||||
st->print("\n\t");
|
||||
|
@ -616,17 +616,17 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
int framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int framesize = C->output()->frame_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()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -643,7 +643,7 @@ int MachPrologNode::reloc() const {
|
|||
#ifndef PRODUCT
|
||||
void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
|
||||
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");
|
||||
// Remove two words for return addr and rbp,
|
||||
framesize -= 2*wordSize;
|
||||
|
@ -682,7 +682,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
_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");
|
||||
// Remove two words for return addr and rbp,
|
||||
framesize -= 2*wordSize;
|
||||
|
|
|
@ -785,7 +785,7 @@ void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
|
|||
//=============================================================================
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -814,13 +814,13 @@ void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
|||
void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
|
||||
Compile* C = ra_->C;
|
||||
|
||||
int framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int framesize = C->output()->frame_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
|
||||
// Remove wordSize for return addr which is already pushed.
|
||||
framesize -= wordSize;
|
||||
|
||||
if (C->need_stack_bang(bangsize)) {
|
||||
if (C->output()->need_stack_bang(bangsize)) {
|
||||
framesize -= wordSize;
|
||||
st->print("# stack bang (%d bytes)", bangsize);
|
||||
st->print("\n\t");
|
||||
|
@ -874,8 +874,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
|||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
int framesize = C->frame_size_in_bytes();
|
||||
int bangsize = C->bang_size_in_bytes();
|
||||
int framesize = C->output()->frame_size_in_bytes();
|
||||
int bangsize = C->output()->bang_size_in_bytes();
|
||||
|
||||
if (C->clinit_barrier_on_entry()) {
|
||||
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);
|
||||
}
|
||||
|
||||
__ 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()) {
|
||||
// NOTE: We set the table base offset here because users might be
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
@ -925,7 +925,7 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const
|
|||
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");
|
||||
// Remove word for return adr already pushed
|
||||
// and RBP
|
||||
|
@ -966,7 +966,7 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
|
|||
__ 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");
|
||||
// Remove word for return adr already pushed
|
||||
// and RBP
|
||||
|
|
|
@ -3374,7 +3374,7 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
|
|||
}
|
||||
|
||||
// Start code line.
|
||||
encoding->add_code(" _constant = C->constant_table().add");
|
||||
encoding->add_code(" _constant = C->output()->constant_table().add");
|
||||
|
||||
// Parse everything in ( ) expression.
|
||||
encoding->add_code("(this, ");
|
||||
|
|
|
@ -237,6 +237,7 @@ int main(int argc, char *argv[])
|
|||
AD.addInclude(AD._HPP_file, "memory/allocation.hpp");
|
||||
AD.addInclude(AD._HPP_file, "oops/compressedOops.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/node.hpp");
|
||||
AD.addInclude(AD._HPP_file, "opto/regalloc.hpp");
|
||||
|
|
|
@ -2605,7 +2605,7 @@ void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
|
|||
|
||||
// For MachConstantNodes which are ideal jump nodes, fill the jump table.
|
||||
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.
|
||||
|
@ -2679,7 +2679,7 @@ void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
|
|||
|
||||
// For ideal jump nodes, add a jump-table entry.
|
||||
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,
|
||||
|
|
|
@ -395,6 +395,9 @@ public:
|
|||
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 CompileLog* get_log(CompilerThread* ct);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "opto/macro.hpp"
|
||||
#include "opto/memnode.hpp"
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/regalloc.hpp"
|
||||
#include "opto/rootnode.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* 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);
|
||||
}
|
||||
|
||||
|
@ -130,7 +131,7 @@ Label* ZLoadBarrierStubC2::entry() {
|
|||
// 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
|
||||
// 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() {
|
||||
|
@ -152,7 +153,7 @@ void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const {
|
|||
|
||||
for (int i = 0; i < stubs->length(); i++) {
|
||||
// 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");
|
||||
return;
|
||||
}
|
||||
|
@ -165,12 +166,12 @@ void ZBarrierSetC2::emit_stubs(CodeBuffer& cb) const {
|
|||
|
||||
int ZBarrierSetC2::estimate_stub_size() const {
|
||||
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();
|
||||
int size = 0;
|
||||
|
||||
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);
|
||||
ZBarrierSet::assembler()->generate_c2_load_barrier_stub(&masm, stubs->at(i));
|
||||
size += cb.insts_size();
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "opto/compile.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/phase.hpp"
|
||||
#include "opto/regalloc.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?
|
||||
void Compile::BuildOopMaps() {
|
||||
TracePhase tp("bldOopMaps", &timers[_t_buildOopMaps]);
|
||||
void PhaseOutput::BuildOopMaps() {
|
||||
Compile::TracePhase tp("bldOopMaps", &timers[_t_buildOopMaps]);
|
||||
// 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.
|
||||
// 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();
|
||||
Block_List worklist; // Worklist of pending blocks
|
||||
|
@ -578,17 +579,17 @@ void Compile::BuildOopMaps() {
|
|||
// Compute a backwards liveness per register. Needs a bitarray of
|
||||
// #blocks x (#registers, rounded up to ints)
|
||||
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
|
||||
|
||||
// Array mapping blocks to completed oopflows
|
||||
OopFlow **flows = NEW_ARENA_ARRAY(A, OopFlow*, _cfg->number_of_blocks());
|
||||
memset( flows, 0, _cfg->number_of_blocks() * sizeof(OopFlow*) );
|
||||
OopFlow **flows = NEW_ARENA_ARRAY(A, OopFlow*, C->cfg()->number_of_blocks());
|
||||
memset( flows, 0, C->cfg()->number_of_blocks() * sizeof(OopFlow*) );
|
||||
|
||||
|
||||
// Do the first block 'by hand' to prime the worklist
|
||||
Block *entry = _cfg->get_block(1);
|
||||
OopFlow *rootflow = OopFlow::make(A,max_reg,this);
|
||||
Block *entry = C->cfg()->get_block(1);
|
||||
OopFlow *rootflow = OopFlow::make(A,max_reg,C);
|
||||
// Initialize to 'bottom' (not 'top')
|
||||
memset( rootflow->_callees, OptoReg::Bad, max_reg*sizeof(short) );
|
||||
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
|
||||
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++ )
|
||||
worklist.push(entry->_succs[i]);
|
||||
|
||||
|
@ -613,7 +614,7 @@ void Compile::BuildOopMaps() {
|
|||
|
||||
Block *b = worklist.pop();
|
||||
// Ignore root block
|
||||
if (b == _cfg->get_root_block()) {
|
||||
if (b == C->cfg()->get_root_block()) {
|
||||
continue;
|
||||
}
|
||||
// Block is already done? Happens if block has several predecessors,
|
||||
|
@ -627,7 +628,7 @@ void Compile::BuildOopMaps() {
|
|||
Block *pred = (Block*)((intptr_t)0xdeadbeef);
|
||||
// Scan this block's preds to find a done predecessor
|
||||
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];
|
||||
if( p_flow ) { // Predecessor is done
|
||||
assert( p_flow->_b == p, "cross check" );
|
||||
|
@ -674,7 +675,7 @@ void Compile::BuildOopMaps() {
|
|||
// Now push flow forward
|
||||
flows[b->_pre_order] = flow;// Mark flow for this block
|
||||
flow->_b = b;
|
||||
flow->compute_reach( _regalloc, max_reg, safehash );
|
||||
flow->compute_reach( C->regalloc(), max_reg, safehash );
|
||||
|
||||
// Now push children onto worklist
|
||||
for( i=0; i<b->_num_succs; i++ )
|
||||
|
|
|
@ -108,7 +108,7 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, Dir
|
|||
|
||||
while (!env->failing()) {
|
||||
// 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.
|
||||
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) {
|
||||
// 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
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
#include "memory/resourceArea.hpp"
|
||||
#include "opto/connode.hpp"
|
||||
#include "opto/live.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/phase.hpp"
|
||||
#include "opto/regalloc.hpp"
|
||||
#include "opto/regmask.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
|
||||
class Matcher;
|
||||
class PhaseCFG;
|
||||
|
|
|
@ -250,7 +250,7 @@ void Compile::print_statistics() {
|
|||
Parse::print_statistics();
|
||||
PhaseCCP::print_statistics();
|
||||
PhaseRegAlloc::print_statistics();
|
||||
Scheduling::print_statistics();
|
||||
PhaseOutput::print_statistics();
|
||||
PhasePeephole::print_statistics();
|
||||
PhaseIdealLoop::print_statistics();
|
||||
if (xtty != NULL) xtty->tail("statistics");
|
||||
|
@ -262,17 +262,6 @@ void Compile::print_statistics() {
|
|||
}
|
||||
#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) {
|
||||
for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) {
|
||||
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*/);)
|
||||
}
|
||||
|
||||
//------------------------------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---------------------------------
|
||||
class CompileWrapper : public StackObj {
|
||||
|
@ -468,14 +439,11 @@ CompileWrapper::CompileWrapper(Compile* compile) : _compile(compile) {
|
|||
compile->set_indexSet_free_block_list(NULL);
|
||||
compile->init_type_arena();
|
||||
Type::Initialize(compile);
|
||||
_compile->set_scratch_buffer_blob(NULL);
|
||||
_compile->begin_method();
|
||||
_compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
|
||||
}
|
||||
CompileWrapper::~CompileWrapper() {
|
||||
_compile->end_method();
|
||||
if (_compile->scratch_buffer_blob() != NULL)
|
||||
BufferBlob::free(_compile->scratch_buffer_blob());
|
||||
_compile->env()->set_compiler_data(NULL);
|
||||
}
|
||||
|
||||
|
@ -520,104 +488,6 @@ void Compile::print_compile_messages() {
|
|||
#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-------------------------------
|
||||
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.
|
||||
|
||||
|
||||
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)
|
||||
: Phase(Compiler),
|
||||
_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_entry_point(NULL),
|
||||
_max_node_limit(MaxNodeLimit),
|
||||
_orig_pc_slot(0),
|
||||
_orig_pc_slot_offset_in_bytes(0),
|
||||
_inlining_progress(false),
|
||||
_inlining_incrementally(false),
|
||||
_do_cleanup(false),
|
||||
|
@ -683,12 +551,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
|||
_replay_inline_data(NULL),
|
||||
_java_calls(0),
|
||||
_inner_loops(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)
|
||||
_interpreter_frame_size(0)
|
||||
#ifndef PRODUCT
|
||||
, _in_dump_cnt(0)
|
||||
#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
|
||||
// for the original deopt pc.
|
||||
|
||||
_orig_pc_slot = fixed_slots();
|
||||
int next_slot = _orig_pc_slot + (sizeof(address) / VMRegImpl::stack_slot_size);
|
||||
int next_slot = fixed_slots() + (sizeof(address) / VMRegImpl::stack_slot_size);
|
||||
set_fixed_slots(next_slot);
|
||||
|
||||
// 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
|
||||
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----------------------------------------
|
||||
|
@ -977,8 +803,6 @@ Compile::Compile( ciEnv* ci_env,
|
|||
_stub_name(stub_name),
|
||||
_stub_entry_point(NULL),
|
||||
_max_node_limit(MaxNodeLimit),
|
||||
_orig_pc_slot(0),
|
||||
_orig_pc_slot_offset_in_bytes(0),
|
||||
_inlining_progress(false),
|
||||
_inlining_incrementally(false),
|
||||
_has_reserved_stack_access(false),
|
||||
|
@ -1016,9 +840,6 @@ Compile::Compile( ciEnv* ci_env,
|
|||
_java_calls(0),
|
||||
_inner_loops(0),
|
||||
_interpreter_frame_size(0),
|
||||
_node_bundling_limit(0),
|
||||
_node_bundling_base(NULL),
|
||||
_code_buffer("Compile::Fill_buffer"),
|
||||
#ifndef PRODUCT
|
||||
_in_dump_cnt(0),
|
||||
#endif
|
||||
|
@ -1053,34 +874,8 @@ Compile::Compile( ciEnv* ci_env,
|
|||
}
|
||||
|
||||
NOT_PRODUCT( verify_graph_edges(); )
|
||||
|
||||
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-------------------------------------------
|
||||
|
@ -2545,8 +2340,11 @@ void Compile::Code_Gen() {
|
|||
|
||||
// Convert Nodes to instruction bits in a buffer
|
||||
{
|
||||
TraceTime tp("output", &timers[_t_output], CITime);
|
||||
Output();
|
||||
TracePhase tp("output", &timers[_t_output]);
|
||||
PhaseOutput output;
|
||||
output.Output();
|
||||
if (failing()) return;
|
||||
output.install();
|
||||
}
|
||||
|
||||
print_method(PHASE_FINAL_CODE);
|
||||
|
@ -2556,143 +2354,6 @@ void Compile::Code_Gen() {
|
|||
_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---------------------------
|
||||
// This class defines counters to help identify when a method
|
||||
// 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-----------------------------
|
||||
// Shortcut important common cases when superklass is exact:
|
||||
// (0) superklass is java.lang.Object (can occur in reflective code)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "asm/codeBuffer.hpp"
|
||||
#include "ci/compilerInterface.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "code/exceptionHandlerTable.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "libadt/dict.hpp"
|
||||
|
@ -48,7 +47,6 @@
|
|||
class AddPNode;
|
||||
class Block;
|
||||
class Bundle;
|
||||
class C2Compiler;
|
||||
class CallGenerator;
|
||||
class CloneMap;
|
||||
class ConnectionGraph;
|
||||
|
@ -72,6 +70,7 @@ class PhaseIterGVN;
|
|||
class PhaseRegAlloc;
|
||||
class PhaseCCP;
|
||||
class PhaseCCP_DCE;
|
||||
class PhaseOutput;
|
||||
class RootNode;
|
||||
class relocInfo;
|
||||
class Scope;
|
||||
|
@ -240,121 +239,6 @@ class Compile : public Phase {
|
|||
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:
|
||||
// Fixed parameters to this compilation.
|
||||
const int _compile_id;
|
||||
|
@ -376,9 +260,6 @@ class Compile : public Phase {
|
|||
int _fixed_slots; // count of frame slots not allocated by the register
|
||||
// allocator i.e. locks, original deopt pc, etc.
|
||||
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
|
||||
bool _inlining_progress; // progress doing incremental inlining?
|
||||
|
@ -457,7 +338,6 @@ class Compile : public Phase {
|
|||
Node* _recent_alloc_ctl;
|
||||
|
||||
// Constant table
|
||||
ConstantTable _constant_table; // The constant table for this compile.
|
||||
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
|
||||
Matcher* _matcher; // Engine to map ideal to machine instructions
|
||||
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)
|
||||
Arena* _indexSet_arena; // control IndexSet allocation within PhaseChaitin
|
||||
void* _indexSet_free_block_list; // free list of IndexSet bit blocks
|
||||
int _interpreter_frame_size;
|
||||
|
||||
uint _node_bundling_limit;
|
||||
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.
|
||||
PhaseOutput* _output;
|
||||
|
||||
void reshape_address(AddPNode* n);
|
||||
|
||||
|
@ -618,6 +483,11 @@ class Compile : public Phase {
|
|||
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.
|
||||
int compile_id() const { return _compile_id; }
|
||||
DirectiveSet* directive() const { return _directive; }
|
||||
|
@ -646,6 +516,7 @@ class Compile : public Phase {
|
|||
address stub_function() const { return _stub_function; }
|
||||
const char* stub_name() const { return _stub_name; }
|
||||
address stub_entry_point() const { return _stub_entry_point; }
|
||||
void set_stub_entry_point(address z) { _stub_entry_point = z; }
|
||||
|
||||
// Control of this compilation.
|
||||
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;
|
||||
DEBUG_ONLY( Unique_Node_List* modified_nodes() const { return _modified_nodes; } )
|
||||
|
||||
// Constant table
|
||||
ConstantTable& constant_table() { return _constant_table; }
|
||||
|
||||
MachConstantBaseNode* mach_constant_base_node();
|
||||
bool has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
|
||||
// Generated by adlc, true if CallNode requires MachConstantBase.
|
||||
|
@ -1124,26 +992,16 @@ class Compile : public Phase {
|
|||
int inner_loops() const { return _inner_loops; }
|
||||
Matcher* matcher() { return _matcher; }
|
||||
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; }
|
||||
Arena* indexSet_arena() { return _indexSet_arena; }
|
||||
void* indexSet_free_block_list() { return _indexSet_free_block_list; }
|
||||
uint node_bundling_limit() { return _node_bundling_limit; }
|
||||
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;
|
||||
DebugInformationRecorder* debug_info() { return env()->debug_info(); }
|
||||
|
||||
void update_interpreter_frame_size(int size) {
|
||||
if (_interpreter_frame_size < size) {
|
||||
_interpreter_frame_size = size;
|
||||
}
|
||||
}
|
||||
int bang_size_in_bytes() const;
|
||||
|
||||
void set_matcher(Matcher* m) { _matcher = m; }
|
||||
//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_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(); }
|
||||
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.
|
||||
// For normal compilations, entry_bci is InvocationEntryBci. For on stack
|
||||
// replacement, entry_bci indicates the bytecode for which to compile a
|
||||
// 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,
|
||||
bool eliminate_boxing, DirectiveSet* directive);
|
||||
|
||||
|
@ -1221,67 +1052,8 @@ class Compile : public Phase {
|
|||
// returns true if adr overlaps with the given alias category
|
||||
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.
|
||||
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
|
||||
// otherwise be preserved. On Intel this includes the return address.
|
||||
|
@ -1364,16 +1136,6 @@ class Compile : public Phase {
|
|||
// End-of-run dumps.
|
||||
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
|
||||
static void adlc_verification() PRODUCT_RETURN;
|
||||
|
||||
|
|
246
src/hotspot/share/opto/constantTable.cpp
Normal file
246
src/hotspot/share/opto/constantTable.cpp
Normal 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);
|
||||
}
|
||||
}
|
151
src/hotspot/share/opto/constantTable.hpp
Normal file
151
src/hotspot/share/opto/constantTable.hpp
Normal 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
|
|
@ -27,6 +27,7 @@
|
|||
#include "memory/universe.hpp"
|
||||
#include "oops/compressedOops.hpp"
|
||||
#include "opto/machnode.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/regalloc.hpp"
|
||||
#include "utilities/vmError.hpp"
|
||||
|
||||
|
@ -154,7 +155,7 @@ uint MachNode::size(PhaseRegAlloc *ra_) const {
|
|||
uint MachNode::emit_size(PhaseRegAlloc *ra_) const {
|
||||
// Emit into a trash buffer and count bytes emitted.
|
||||
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() {
|
||||
// Bind the offset lazily.
|
||||
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);
|
||||
// If called from Compile::scratch_emit_size return the
|
||||
// pre-calculated offset.
|
||||
// NOTE: If the AD file does some table base offset optimizations
|
||||
// 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;
|
||||
}
|
||||
_constant.set_offset(constant_table.table_base_offset() + offset);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define SHARE_OPTO_MACHNODE_HPP
|
||||
|
||||
#include "opto/callnode.hpp"
|
||||
#include "opto/constantTable.hpp"
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/multnode.hpp"
|
||||
#include "opto/node.hpp"
|
||||
|
@ -447,7 +448,7 @@ public:
|
|||
// Machine node that holds a constant which is stored in the constant table.
|
||||
class MachConstantNode : public MachTypeNode {
|
||||
protected:
|
||||
Compile::Constant _constant; // This node's constant.
|
||||
ConstantTable::Constant _constant; // This node's constant.
|
||||
|
||||
public:
|
||||
MachConstantNode() : MachTypeNode() {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,20 +26,24 @@
|
|||
#define SHARE_OPTO_OUTPUT_HPP
|
||||
|
||||
#include "opto/ad.hpp"
|
||||
#include "opto/block.hpp"
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/constantTable.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 Bundle;
|
||||
class Block;
|
||||
class Block_Array;
|
||||
class ciMethod;
|
||||
class Compile;
|
||||
class MachNode;
|
||||
class MachSafePointNode;
|
||||
class Node;
|
||||
class Node_Array;
|
||||
class Node_List;
|
||||
class PhaseCFG;
|
||||
class PhaseChaitin;
|
||||
class Pipeline_Use_Element;
|
||||
class Pipeline_Use;
|
||||
#ifndef PRODUCT
|
||||
#define DEBUG_ARG(x) , x
|
||||
#else
|
||||
|
@ -51,167 +55,157 @@ enum {
|
|||
initial_const_capacity = 4 * 1024
|
||||
};
|
||||
|
||||
//------------------------------Scheduling----------------------------------
|
||||
// This class contains all the information necessary to implement instruction
|
||||
// scheduling and bundling.
|
||||
class Scheduling {
|
||||
class BufferSizingData {
|
||||
public:
|
||||
int _stub;
|
||||
int _code;
|
||||
int _const;
|
||||
int _reloc;
|
||||
|
||||
BufferSizingData() :
|
||||
_stub(0),
|
||||
_code(0),
|
||||
_const(0),
|
||||
_reloc(0)
|
||||
{ };
|
||||
};
|
||||
|
||||
class PhaseOutput : public Phase {
|
||||
private:
|
||||
// Arena to use
|
||||
Arena *_arena;
|
||||
// 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.
|
||||
|
||||
// Control-Flow Graph info
|
||||
PhaseCFG *_cfg;
|
||||
int _frame_slots; // Size of total frame in stack slots
|
||||
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;
|
||||
Bundle* _node_bundling_base; // Information for instruction bundling
|
||||
|
||||
// List of scheduled nodes. Generated in reverse order
|
||||
Node_List _scheduled;
|
||||
// For deopt
|
||||
int _orig_pc_slot;
|
||||
int _orig_pc_slot_offset_in_bytes;
|
||||
|
||||
// List of nodes currently available for choosing for scheduling
|
||||
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;
|
||||
ConstantTable _constant_table; // The constant table for this compilation unit.
|
||||
|
||||
public:
|
||||
Scheduling(Arena *arena, Compile &compile);
|
||||
PhaseOutput();
|
||||
~PhaseOutput();
|
||||
|
||||
// Destructor
|
||||
NOT_PRODUCT( ~Scheduling(); )
|
||||
// Convert Nodes to instruction bits and pass off to the VM
|
||||
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 step(uint i);
|
||||
void install_code(ciMethod* target,
|
||||
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,
|
||||
// at a branch target)
|
||||
void step_and_clear();
|
||||
void install_stub(const char* stub_name,
|
||||
bool caller_must_gc_arguments);
|
||||
|
||||
Bundle* node_bundling(const Node *n) {
|
||||
assert(valid_bundle_info(n), "oob");
|
||||
return (&_node_bundling_base[n->_idx]);
|
||||
}
|
||||
// Constant table
|
||||
ConstantTable& constant_table() { return _constant_table; }
|
||||
|
||||
bool valid_bundle_info(const Node *n) const {
|
||||
return (_node_bundling_limit > n->_idx);
|
||||
}
|
||||
// The architecture description provides short branch variants for some long
|
||||
// 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 {
|
||||
return (_node_bundling_limit > n->_idx && _node_bundling_base[n->_idx].starts_bundle());
|
||||
}
|
||||
void Process_OopMap_Node(MachNode *mach, int current_offset);
|
||||
|
||||
// Do the scheduling
|
||||
void DoScheduling();
|
||||
// Initialize code buffer
|
||||
void estimate_buffer_size(int& const_req);
|
||||
CodeBuffer* init_buffer(BufferSizingData& buf_sizes);
|
||||
|
||||
// Compute the local latencies walking forward over the list of
|
||||
// nodes for a basic block
|
||||
void ComputeLocalLatenciesForward(const Block *bb);
|
||||
// Write out basic block data to code buffer
|
||||
void fill_buffer(CodeBuffer* cb, uint* blk_starts);
|
||||
|
||||
// Compute the register antidependencies within a basic block
|
||||
void ComputeRegisterAntidependencies(Block *bb);
|
||||
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 );
|
||||
// Compute the information for the exception tables
|
||||
void FillExceptionTables(uint cnt, uint *call_returns, uint *inct_starts, Label *blk_labels);
|
||||
|
||||
// Add a node to the current bundle
|
||||
void AddNodeToBundle(Node *n, const Block *bb);
|
||||
// Perform instruction scheduling and bundling over the sequence of
|
||||
// instructions in backwards order.
|
||||
void ScheduleAndBundle();
|
||||
|
||||
// Add a node to the list of available nodes
|
||||
void AddNodeToAvailableList(Node *n);
|
||||
void install();
|
||||
|
||||
// Compute the local use count for the nodes in a block, and compute
|
||||
// the list of instructions with no uses in the block as available
|
||||
void ComputeUseCount(const Block *bb);
|
||||
// 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; }
|
||||
|
||||
// Choose an instruction from the available list to add to the bundle
|
||||
Node * ChooseNodeToBundle();
|
||||
// Scratch buffer
|
||||
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
|
||||
bool NodeFitsInBundle(Node *n);
|
||||
// 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; }
|
||||
|
||||
// Decrement the use count for a node
|
||||
void DecrementUseCounts(Node *n, const Block *bb);
|
||||
enum ScratchBufferBlob {
|
||||
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.
|
||||
void garbage_collect_pinch_nodes();
|
||||
// Clean up a pinch node for reuse (helper for above).
|
||||
void cleanup_pinch( Node *pinch );
|
||||
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; }
|
||||
|
||||
// Information for statistics gathering
|
||||
#ifndef PRODUCT
|
||||
private:
|
||||
// Gather information on size of nops relative to total
|
||||
uint _branches, _unconditional_delays;
|
||||
int bang_size_in_bytes() const;
|
||||
|
||||
static uint _total_nop_size, _total_method_size;
|
||||
static uint _total_branches, _total_unconditional_delays;
|
||||
static uint _total_instructions_per_bundle[Pipeline::_max_instrs_per_cycle+1];
|
||||
uint node_bundling_limit();
|
||||
Bundle* 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; }
|
||||
|
||||
public:
|
||||
static void print_statistics();
|
||||
Bundle* node_bundling(const Node *n);
|
||||
bool valid_bundle_info(const Node *n);
|
||||
|
||||
static void increment_instructions_per_bundle(uint i) {
|
||||
_total_instructions_per_bundle[i]++;
|
||||
}
|
||||
bool starts_bundle(const Node *n) const;
|
||||
|
||||
static void increment_nop_size(uint s) {
|
||||
_total_nop_size += s;
|
||||
}
|
||||
|
||||
static void increment_method_size(uint s) {
|
||||
_total_method_size += s;
|
||||
}
|
||||
// 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
|
||||
|
||||
// Build OopMaps for each GC point
|
||||
void BuildOopMaps();
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void print_statistics();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_OPTO_OUTPUT_HPP
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
Ideal_Loop, // Find idealized trip-counted loops
|
||||
Macro_Expand, // Expand macro nodes
|
||||
Peephole, // Apply peephole optimizations
|
||||
Output,
|
||||
last_phase
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "opto/matcher.hpp"
|
||||
#include "opto/memnode.hpp"
|
||||
#include "opto/mulnode.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/runtime.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue