This commit is contained in:
Rickard Bäckman 2015-08-13 19:36:54 +02:00
commit a4777426de
15 changed files with 38 additions and 35 deletions

View File

@ -416,7 +416,8 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
int jmp_off = __ offset();
__ jmp(_patch_site_entry);
// Add enough nops so deoptimization can overwrite the jmp above with a call
// and not destroy the world.
// and not destroy the world. We cannot use fat nops here, since the concurrent
// code rewrite may transiently create the illegal instruction sequence.
for (int j = __ offset() ; j < jmp_off + 5 ; j++ ) {
__ nop();
}

View File

@ -345,9 +345,7 @@ int LIR_Assembler::check_icache() {
const bool do_post_padding = VerifyOops || UseCompressedClassPointers;
if (!do_post_padding) {
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment
while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
__ nop();
}
__ align(CodeEntryAlignment, __ offset() + ic_cmp_size);
}
int offset = __ offset();
__ inline_cache_check(receiver, IC_Klass);
@ -2861,9 +2859,7 @@ void LIR_Assembler::align_call(LIR_Code code) {
case lir_virtual_call: // currently, sparc-specific for niagara
default: ShouldNotReachHere();
}
while (offset++ % BytesPerWord != 0) {
__ nop();
}
__ align(BytesPerWord, offset);
}
}
@ -2902,10 +2898,7 @@ void LIR_Assembler::emit_static_call_stub() {
int start = __ offset();
if (os::is_MP()) {
// make sure that the displacement word of the call ends up word aligned
int offset = __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset;
while (offset++ % BytesPerWord != 0) {
__ nop();
}
__ align(BytesPerWord, __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset);
}
__ relocate(static_stub_Relocation::spec(call_pc));
__ mov_metadata(rbx, (Metadata*)NULL);

View File

@ -970,8 +970,12 @@ void MacroAssembler::addss(XMMRegister dst, AddressLiteral src) {
}
void MacroAssembler::align(int modulus) {
if (offset() % modulus != 0) {
nop(modulus - (offset() % modulus));
align(modulus, offset());
}
void MacroAssembler::align(int modulus, int target) {
if (target % modulus != 0) {
nop(modulus - (target % modulus));
}
}

View File

@ -192,6 +192,7 @@ class MacroAssembler: public Assembler {
// Alignment
void align(int modulus);
void align(int modulus, int target);
// A 5 byte nop that is safe for patching (see patch_verified_entry)
void fat_nop();

View File

@ -33,7 +33,9 @@
#include "runtime/os.hpp"
void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
// we must have enough patching space so that call can be inserted
// We must have enough patching space so that call can be inserted.
// We cannot use fat nops here, since the concurrent code rewrite may transiently
// create the illegal instruction sequence.
while ((intx) _masm->pc() - (intx) patch->pc_start() < NativeCall::instruction_size) {
_masm->nop();
}
@ -592,9 +594,7 @@ void LIR_Assembler::emit_op1(LIR_Op1* op) {
void LIR_Assembler::emit_op0(LIR_Op0* op) {
switch (op->code()) {
case lir_word_align: {
while (code_offset() % BytesPerWord != 0) {
_masm->nop();
}
_masm->align(BytesPerWord);
break;
}

View File

@ -393,7 +393,7 @@ uint PhaseCFG::build_cfg() {
VectorSet visited(a);
// Allocate stack with enough space to avoid frequent realloc
Node_Stack nstack(a, C->unique() >> 1);
Node_Stack nstack(a, C->live_nodes() >> 1);
nstack.push(_root, 0);
uint sum = 0; // Counter for blocks

View File

@ -802,7 +802,7 @@ PhiNode* PhiNode::split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) cons
Compile *C = igvn->C;
Arena *a = Thread::current()->resource_area();
Node_Array node_map = new Node_Array(a);
Node_Stack stack(a, C->unique() >> 4);
Node_Stack stack(a, C->live_nodes() >> 4);
PhiNode *nphi = slice_memory(at);
igvn->register_new_node_with_optimizer( nphi );
node_map.map(_idx, nphi);

View File

@ -3315,7 +3315,7 @@ bool Compile::final_graph_reshaping() {
// Visit everybody reachable!
// Allocate stack of size C->unique()/2 to avoid frequent realloc
Node_Stack nstack(unique() >> 1);
Node_Stack nstack(live_nodes() >> 1);
final_graph_reshaping_walk(nstack, root(), frc);
// Check for unreachable (from below) code (i.e., infinite loops).

View File

@ -507,7 +507,7 @@ void PhaseIdealLoop::Dominators() {
// 'semi' as vertex to DFS mapping. Set 'parent' to DFS parent.
int NTarjan::DFS( NTarjan *ntarjan, VectorSet &visited, PhaseIdealLoop *pil, uint *dfsorder) {
// Allocate stack of size C->unique()/8 to avoid frequent realloc
GrowableArray <Node *> dfstack(pil->C->unique() >> 3);
GrowableArray <Node *> dfstack(pil->C->live_nodes() >> 3);
Node *b = pil->C->root();
int dfsnum = 1;
dfsorder[b->_idx] = dfsnum; // Cache parent's dfsnum for a later use

View File

@ -107,8 +107,8 @@ static bool is_dominator(Block* d, Block* n) {
//------------------------------schedule_pinned_nodes--------------------------
// Set the basic block for Nodes pinned into blocks
void PhaseCFG::schedule_pinned_nodes(VectorSet &visited) {
// Allocate node stack of size C->unique()+8 to avoid frequent realloc
GrowableArray <Node *> spstack(C->unique() + 8);
// Allocate node stack of size C->live_nodes()+8 to avoid frequent realloc
GrowableArray <Node *> spstack(C->live_nodes() + 8);
spstack.push(_root);
while (spstack.is_nonempty()) {
Node* node = spstack.pop();
@ -1310,7 +1310,7 @@ void PhaseCFG::global_code_motion() {
visited.Clear();
Node_List stack(arena);
// Pre-grow the list
stack.map((C->unique() >> 1) + 16, NULL);
stack.map((C->live_nodes() >> 1) + 16, NULL);
if (!schedule_early(visited, stack)) {
// Bailout without retry
C->record_method_not_compilable("early schedule failed");

View File

@ -1282,7 +1282,7 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
if (C->do_vector_loop() && (PrintOpto && VerifyLoopOptimizations || TraceLoopOpts)) {
Arena* arena = Thread::current()->resource_area();
Node_Stack stack(arena, C->unique() >> 2);
Node_Stack stack(arena, C->live_nodes() >> 2);
Node_List rpo_list;
VectorSet visited(arena);
visited.set(loop_head->_idx);

View File

@ -2231,7 +2231,7 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
// _nodes array holds the earliest legal controlling CFG node.
// Allocate stack with enough space to avoid frequent realloc
int stack_size = (C->unique() >> 1) + 16; // (unique>>1)+16 from Java2D stats
int stack_size = (C->live_nodes() >> 1) + 16; // (live_nodes>>1)+16 from Java2D stats
Node_Stack nstack( a, stack_size );
visited.Clear();
@ -2691,7 +2691,7 @@ void PhaseIdealLoop::recompute_dom_depth() {
}
}
if (_dom_stk == NULL) {
uint init_size = C->unique() / 100; // Guess that 1/100 is a reasonable initial size.
uint init_size = C->live_nodes() / 100; // Guess that 1/100 is a reasonable initial size.
if (init_size < 10) init_size = 10;
_dom_stk = new GrowableArray<uint>(init_size);
}
@ -2781,8 +2781,8 @@ IdealLoopTree *PhaseIdealLoop::sort( IdealLoopTree *loop, IdealLoopTree *innermo
// The sort is of size number-of-control-children, which generally limits
// it to size 2 (i.e., I just choose between my 2 target loops).
void PhaseIdealLoop::build_loop_tree() {
// Allocate stack of size C->unique()/2 to avoid frequent realloc
GrowableArray <Node *> bltstack(C->unique() >> 1);
// Allocate stack of size C->live_nodes()/2 to avoid frequent realloc
GrowableArray <Node *> bltstack(C->live_nodes() >> 1);
Node *n = C->root();
bltstack.push(n);
int pre_order = 1;
@ -3672,7 +3672,7 @@ void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node*
void PhaseIdealLoop::dump( ) const {
ResourceMark rm;
Arena* arena = Thread::current()->resource_area();
Node_Stack stack(arena, C->unique() >> 2);
Node_Stack stack(arena, C->live_nodes() >> 2);
Node_List rpo_list;
VectorSet visited(arena);
visited.set(C->top()->_idx);

View File

@ -2050,7 +2050,7 @@ bool Matcher::is_bmi_pattern(Node *n, Node *m) {
// Set bits if Node is shared or otherwise a root
void Matcher::find_shared( Node *n ) {
// Allocate stack of size C->unique() * 2 to avoid frequent realloc
MStack mstack(C->unique() * 2);
MStack mstack(C->live_nodes() * 2);
// Mark nodes as address_visited if they are inputs to an address expression
VectorSet address_visited(Thread::current()->resource_area());
mstack.push(n, Visit); // Don't need to pre-visit root node

View File

@ -1799,7 +1799,7 @@ static void collect_nodes_i(GrowableArray<Node*> *nstack, const Node* start, int
static void dump_nodes(const Node* start, int d, bool only_ctrl) {
if (NotANode(start)) return;
GrowableArray <Node *> nstack(Compile::current()->unique());
GrowableArray <Node *> nstack(Compile::current()->live_nodes());
collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false);
int end = nstack.length();

View File

@ -791,7 +791,7 @@ void PhaseGVN::dead_loop_check( Node *n ) {
//------------------------------PhaseIterGVN-----------------------------------
// Initialize hash table to fresh and clean for +VerifyOpto
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
_stack(C->unique() >> 1),
_stack(C->live_nodes() >> 1),
_delay_transform(false) {
}
@ -808,7 +808,11 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
// Initialize with previous PhaseGVN info from Parser
PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
_worklist(*C->for_igvn()),
_stack(C->unique() >> 1),
// TODO: Before incremental inlining it was allocated only once and it was fine. Now that
// the constructor is used in incremental inlining, this consumes too much memory:
// _stack(C->live_nodes() >> 1),
// So, as a band-aid, we replace this by:
_stack(C->comp_arena(), 32),
_delay_transform(false)
{
uint max;
@ -1638,7 +1642,7 @@ Node *PhaseCCP::transform( Node *n ) {
_nodes.map( n->_idx, new_node ); // Flag as having been cloned
// Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
GrowableArray <Node *> trstack(C->unique() >> 1);
GrowableArray <Node *> trstack(C->live_nodes() >> 1);
trstack.push(new_node); // Process children of cloned node
while ( trstack.is_nonempty() ) {