mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 10:42:45 +00:00
8358560: C2: convert some uses of GrowableArray<Node*> to Unique_Node_List
Reviewed-by: aseoane, chagedorn, bmaillard
This commit is contained in:
parent
29a7130d98
commit
31596cfef9
@ -3970,7 +3970,7 @@ bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
|
||||
// created phi or an existing phi. Sets create_new to indicate whether a new
|
||||
// phi was created. Cache the last newly created phi in the node map.
|
||||
//
|
||||
PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, bool &new_created) {
|
||||
PhiNode* ConnectionGraph::create_split_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, bool& new_created) {
|
||||
Compile *C = _compile;
|
||||
PhaseGVN* igvn = _igvn;
|
||||
new_created = false;
|
||||
@ -4006,7 +4006,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
orig_phi_worklist.append_if_missing(orig_phi);
|
||||
orig_phi_worklist.push(orig_phi);
|
||||
const TypePtr *atype = C->get_adr_type(alias_idx);
|
||||
result = PhiNode::make(orig_phi->in(0), nullptr, Type::MEMORY, atype);
|
||||
C->copy_node_notes_to(result, orig_phi);
|
||||
@ -4021,7 +4021,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
|
||||
// Return a new version of Memory Phi "orig_phi" with the inputs having the
|
||||
// specified alias index.
|
||||
//
|
||||
PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, uint rec_depth) {
|
||||
PhiNode* ConnectionGraph::split_memory_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth) {
|
||||
assert(alias_idx != Compile::AliasIdxBot, "can't split out bottom memory");
|
||||
Compile *C = _compile;
|
||||
PhaseGVN* igvn = _igvn;
|
||||
@ -4030,7 +4030,7 @@ PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, Gro
|
||||
if (!new_phi_created) {
|
||||
return result;
|
||||
}
|
||||
GrowableArray<PhiNode *> phi_list;
|
||||
Unique_Node_List phi_list;
|
||||
GrowableArray<uint> cur_input;
|
||||
PhiNode *phi = orig_phi;
|
||||
uint idx = 1;
|
||||
@ -4070,9 +4070,9 @@ PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, Gro
|
||||
assert((phi->in(i) == nullptr) == (in == nullptr), "inputs must correspond.");
|
||||
}
|
||||
// we have finished processing a Phi, see if there are any more to do
|
||||
finished = (phi_list.length() == 0 );
|
||||
finished = (phi_list.size() == 0);
|
||||
if (!finished) {
|
||||
phi = phi_list.pop();
|
||||
phi = phi_list.pop()->as_Phi();
|
||||
idx = cur_input.pop();
|
||||
PhiNode *prev_result = get_map_phi(phi->_idx);
|
||||
prev_result->set_req(idx++, result);
|
||||
@ -4103,7 +4103,7 @@ Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx,
|
||||
//
|
||||
// Move memory users to their memory slices.
|
||||
//
|
||||
void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis) {
|
||||
void ConnectionGraph::move_inst_mem(Node* n, Unique_Node_List& orig_phis) {
|
||||
Compile* C = _compile;
|
||||
PhaseGVN* igvn = _igvn;
|
||||
const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
|
||||
@ -4176,7 +4176,7 @@ void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phi
|
||||
// is the specified alias index.
|
||||
//
|
||||
#define FIND_INST_MEM_RECURSION_DEPTH_LIMIT 1000
|
||||
Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis, uint rec_depth) {
|
||||
Node* ConnectionGraph::find_inst_mem(Node* orig_mem, int alias_idx, Unique_Node_List& orig_phis, uint rec_depth) {
|
||||
if (rec_depth > FIND_INST_MEM_RECURSION_DEPTH_LIMIT) {
|
||||
_compile->record_failure(_invocation > 0 ? C2Compiler::retry_no_iterative_escape_analysis() : C2Compiler::retry_no_escape_analysis());
|
||||
return nullptr;
|
||||
@ -4269,7 +4269,7 @@ Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArra
|
||||
C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
|
||||
Node *un = result->as_Phi()->unique_input(igvn);
|
||||
if (un != nullptr) {
|
||||
orig_phis.append_if_missing(result->as_Phi());
|
||||
orig_phis.push(result);
|
||||
result = un;
|
||||
} else {
|
||||
break;
|
||||
@ -4324,7 +4324,7 @@ Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArra
|
||||
if (!is_instance) {
|
||||
// Push all non-instance Phis on the orig_phis worklist to update inputs
|
||||
// during Phase 4 if needed.
|
||||
orig_phis.append_if_missing(mphi);
|
||||
orig_phis.push(mphi);
|
||||
} else if (C->get_alias_index(t) != alias_idx) {
|
||||
// Create a new Phi with the specified alias index type.
|
||||
result = split_memory_phi(mphi, alias_idx, orig_phis, rec_depth + 1);
|
||||
@ -4428,8 +4428,8 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
GrowableArray<MergeMemNode*> &mergemem_worklist,
|
||||
Unique_Node_List &reducible_merges) {
|
||||
DEBUG_ONLY(Unique_Node_List reduced_merges;)
|
||||
GrowableArray<Node *> memnode_worklist;
|
||||
GrowableArray<PhiNode *> orig_phis;
|
||||
Unique_Node_List memnode_worklist;
|
||||
Unique_Node_List orig_phis;
|
||||
PhaseIterGVN *igvn = _igvn;
|
||||
uint new_index_start = (uint) _compile->num_alias_types();
|
||||
VectorSet visited;
|
||||
@ -4585,7 +4585,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
}
|
||||
alloc_worklist.append_if_missing(use);
|
||||
} else if (use->is_MemBar()) {
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4682,10 +4682,10 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
Node *use = n->fast_out(i);
|
||||
if(use->is_Mem() && use->in(MemNode::Address) == n) {
|
||||
// Load/store to instance's field
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
} else if (use->is_MemBar()) {
|
||||
if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
} else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes
|
||||
Node* addp2 = find_second_addp(use, n);
|
||||
@ -4714,14 +4714,14 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
} else if (use->Opcode() == Op_EncodeISOArray) {
|
||||
if (use->in(MemNode::Memory) == n || use->in(3) == n) {
|
||||
// EncodeISOArray overwrites destination array
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
} else {
|
||||
uint op = use->Opcode();
|
||||
if ((op == Op_StrCompressedCopy || op == Op_StrInflatedCopy) &&
|
||||
(use->in(MemNode::Memory) == n)) {
|
||||
// They overwrite memory edge corresponding to destination array,
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
} else if (!(op == Op_CmpP || op == Op_Conv2B ||
|
||||
op == Op_CastP2X ||
|
||||
op == Op_FastLock || op == Op_AryEq ||
|
||||
@ -4806,18 +4806,19 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
// Phase 2: Process MemNode's from memnode_worklist. compute new address type and
|
||||
// compute new values for Memory inputs (the Memory inputs are not
|
||||
// actually updated until phase 4.)
|
||||
if (memnode_worklist.length() == 0)
|
||||
if (memnode_worklist.size() == 0) {
|
||||
return; // nothing to do
|
||||
while (memnode_worklist.length() != 0) {
|
||||
}
|
||||
while (memnode_worklist.size() != 0) {
|
||||
Node *n = memnode_worklist.pop();
|
||||
if (visited.test_set(n->_idx)) {
|
||||
continue;
|
||||
}
|
||||
if (n->is_Phi()) {
|
||||
if ((uint) _compile->get_alias_index(n->as_Phi()->adr_type()) < new_index_start) {
|
||||
if ((uint) _compile->get_alias_index(n->adr_type()) < new_index_start) {
|
||||
// Push memory phis on the orig_phis worklist to update
|
||||
// during Phase 4 if needed.
|
||||
orig_phis.append_if_missing(n->as_Phi());
|
||||
orig_phis.push(n);
|
||||
}
|
||||
} else if (n->is_ClearArray()) {
|
||||
// we don't need to do anything, but the users must be pushed
|
||||
@ -4882,17 +4883,17 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||
Node *use = n->fast_out(i);
|
||||
if (use->is_Phi() || use->is_ClearArray()) {
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
} else if (use->is_Mem() && use->in(MemNode::Memory) == n) {
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
} else if (use->is_MemBar() || use->is_CallLeaf()) {
|
||||
if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
} else if (use->is_Proj()) {
|
||||
assert(n->is_Initialize(), "We only push projections of Initialize");
|
||||
if (use->as_Proj()->_con == TypeFunc::Memory) { // Ignore precedent edge
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
} else if(use->is_Mem()) {
|
||||
@ -4902,14 +4903,14 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
} else if (use->Opcode() == Op_EncodeISOArray) {
|
||||
if (use->in(MemNode::Memory) == n || use->in(3) == n) {
|
||||
// EncodeISOArray overwrites destination array
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
}
|
||||
} else {
|
||||
uint op = use->Opcode();
|
||||
if ((use->in(MemNode::Memory) == n) &&
|
||||
(op == Op_StrCompressedCopy || op == Op_StrInflatedCopy)) {
|
||||
// They overwrite memory edge corresponding to destination array,
|
||||
memnode_worklist.append_if_missing(use);
|
||||
memnode_worklist.push(use);
|
||||
} else if (!(BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(use) ||
|
||||
op == Op_AryEq || op == Op_StrComp || op == Op_CountPositives ||
|
||||
op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || op == Op_VectorizedHashCode ||
|
||||
@ -5018,8 +5019,8 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
|
||||
// to recursively process Phi's encountered on the input memory
|
||||
// chains as is done in split_memory_phi() since they will
|
||||
// also be processed here.
|
||||
for (int j = 0; j < orig_phis.length(); j++) {
|
||||
PhiNode *phi = orig_phis.at(j);
|
||||
for (uint j = 0; j < orig_phis.size(); j++) {
|
||||
PhiNode* phi = orig_phis.at(j)->as_Phi();
|
||||
int alias_idx = _compile->get_alias_index(phi->adr_type());
|
||||
igvn->hash_delete(phi);
|
||||
for (uint i = 1; i < phi->req(); i++) {
|
||||
|
||||
@ -556,11 +556,11 @@ private:
|
||||
// Helper methods for unique types split.
|
||||
bool split_AddP(Node *addp, Node *base);
|
||||
|
||||
PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, bool &new_created);
|
||||
PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, uint rec_depth);
|
||||
PhiNode* create_split_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, bool& new_created);
|
||||
PhiNode* split_memory_phi(PhiNode* orig_phi, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth);
|
||||
|
||||
void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis);
|
||||
Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, uint rec_depth = 0);
|
||||
void move_inst_mem(Node* n, Unique_Node_List& orig_phis);
|
||||
Node* find_inst_mem(Node* mem, int alias_idx, Unique_Node_List& orig_phi_worklist, uint rec_depth = 0);
|
||||
Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
|
||||
|
||||
Node_Array _node_map; // used for bookkeeping during type splitting
|
||||
|
||||
@ -595,7 +595,7 @@ private:
|
||||
};
|
||||
|
||||
GrowableArray<DefUsePair> _queue;
|
||||
GrowableArray<MergeMemNode*> _worklist_visited; // visited mergemem nodes
|
||||
Unique_Node_List _worklist_visited; // visited mergemem nodes
|
||||
|
||||
bool already_enqueued(Node* def_mem, PhiNode* use_phi) const {
|
||||
// def_mem is one of the inputs of use_phi and at least one input of use_phi is
|
||||
@ -635,9 +635,11 @@ public:
|
||||
void push(Node* def_mem_state, Node* use_mem_state) {
|
||||
if (use_mem_state->is_MergeMem()) {
|
||||
// Be sure we don't get into combinatorial problems.
|
||||
if (!_worklist_visited.append_if_missing(use_mem_state->as_MergeMem())) {
|
||||
return; // already on work list; do not repeat
|
||||
if (_worklist_visited.member(use_mem_state)) {
|
||||
// already on work list; do not repeat
|
||||
return;
|
||||
}
|
||||
_worklist_visited.push(use_mem_state);
|
||||
} else if (use_mem_state->is_Phi()) {
|
||||
// A Phi could have the same mem as input multiple times. If that's the case, we don't need to enqueue it
|
||||
// more than once. We otherwise allow phis to be repeated; they can merge two relevant states.
|
||||
|
||||
@ -612,7 +612,7 @@ Node* PhaseMacroExpand::value_from_mem(Node* origin, Node* ctl, BasicType ft, co
|
||||
}
|
||||
|
||||
// Check the possibility of scalar replacement.
|
||||
bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode *alloc, GrowableArray <SafePointNode *>* safepoints) {
|
||||
bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode* alloc, Unique_Node_List* safepoints) {
|
||||
// Scan the uses of the allocation to check for anything that would
|
||||
// prevent us from eliminating it.
|
||||
NOT_PRODUCT( const char* fail_eliminate = nullptr; )
|
||||
@ -700,7 +700,7 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode
|
||||
NOT_PRODUCT(fail_eliminate = "null or TOP memory";)
|
||||
can_eliminate = false;
|
||||
} else if (!reduce_merge_precheck) {
|
||||
safepoints->append_if_missing(sfpt);
|
||||
safepoints->push(sfpt);
|
||||
}
|
||||
} else if (reduce_merge_precheck &&
|
||||
(use->is_Phi() || use->is_EncodeP() ||
|
||||
@ -759,7 +759,7 @@ bool PhaseMacroExpand::can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode
|
||||
return can_eliminate;
|
||||
}
|
||||
|
||||
void PhaseMacroExpand::undo_previous_scalarizations(GrowableArray <SafePointNode *> safepoints_done, AllocateNode* alloc) {
|
||||
void PhaseMacroExpand::undo_previous_scalarizations(Unique_Node_List& safepoints_done, AllocateNode* alloc) {
|
||||
Node* res = alloc->result_cast();
|
||||
int nfields = 0;
|
||||
assert(res == nullptr || res->is_CheckCastPP(), "unexpected AllocateNode result");
|
||||
@ -779,8 +779,8 @@ void PhaseMacroExpand::undo_previous_scalarizations(GrowableArray <SafePointNode
|
||||
}
|
||||
|
||||
// rollback processed safepoints
|
||||
while (safepoints_done.length() > 0) {
|
||||
SafePointNode* sfpt_done = safepoints_done.pop();
|
||||
while (safepoints_done.size() > 0) {
|
||||
SafePointNode* sfpt_done = safepoints_done.pop()->as_SafePoint();
|
||||
|
||||
SafePointNode::NodeEdgeTempStorage non_debug_edges_worklist(igvn());
|
||||
|
||||
@ -978,16 +978,16 @@ SafePointScalarObjectNode* PhaseMacroExpand::create_scalarized_object_descriptio
|
||||
}
|
||||
|
||||
// Do scalar replacement.
|
||||
bool PhaseMacroExpand::scalar_replacement(AllocateNode* alloc, GrowableArray<SafePointNode*>& safepoints) {
|
||||
GrowableArray<SafePointNode*> safepoints_done;
|
||||
bool PhaseMacroExpand::scalar_replacement(AllocateNode* alloc, Unique_Node_List& safepoints) {
|
||||
Unique_Node_List safepoints_done;
|
||||
Node* res = alloc->result_cast();
|
||||
assert(res == nullptr || res->is_CheckCastPP(), "unexpected AllocateNode result");
|
||||
|
||||
// Process the safepoint uses
|
||||
while (safepoints.length() > 0) {
|
||||
SafePointNode* sfpt = safepoints.pop();
|
||||
while (safepoints.size() > 0) {
|
||||
SafePointNode* sfpt = safepoints.pop()->as_SafePoint();
|
||||
|
||||
SafePointNode::NodeEdgeTempStorage non_debug_edges_worklist(igvn());
|
||||
SafePointNode::NodeEdgeTempStorage non_debug_edges_worklist(igvn());
|
||||
|
||||
// All sfpt inputs are implicitly included into debug info during the scalarization process below.
|
||||
// Keep non-debug inputs separately, so they stay non-debug.
|
||||
@ -1010,7 +1010,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode* alloc, GrowableArray<Saf
|
||||
_igvn._worklist.push(sfpt);
|
||||
|
||||
// keep it for rollback
|
||||
safepoints_done.append_if_missing(sfpt);
|
||||
safepoints_done.push(sfpt);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1199,7 +1199,7 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
|
||||
|
||||
alloc->extract_projections(&_callprojs, false /*separate_io_proj*/, false /*do_asserts*/);
|
||||
|
||||
GrowableArray <SafePointNode *> safepoints;
|
||||
Unique_Node_List safepoints;
|
||||
if (!can_eliminate_allocation(&_igvn, alloc, &safepoints)) {
|
||||
return false;
|
||||
}
|
||||
@ -1209,7 +1209,7 @@ bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
|
||||
// We can only eliminate allocation if all debug info references
|
||||
// are already replaced with SafePointScalarObject because
|
||||
// we can't search for a fields value without instance_id.
|
||||
if (safepoints.length() > 0) {
|
||||
if (safepoints.size() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,8 +109,8 @@ private:
|
||||
|
||||
bool eliminate_boxing_node(CallStaticJavaNode *boxing);
|
||||
bool eliminate_allocate_node(AllocateNode *alloc);
|
||||
void undo_previous_scalarizations(GrowableArray <SafePointNode *> safepoints_done, AllocateNode* alloc);
|
||||
bool scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints);
|
||||
void undo_previous_scalarizations(Unique_Node_List& safepoints_done, AllocateNode* alloc);
|
||||
bool scalar_replacement(AllocateNode* alloc, Unique_Node_List& safepoints);
|
||||
void process_users_of_allocation(CallNode *alloc);
|
||||
|
||||
void eliminate_gc_barrier(Node *p2x);
|
||||
@ -218,7 +218,7 @@ public:
|
||||
void eliminate_opaque_looplimit_macro_nodes();
|
||||
|
||||
SafePointScalarObjectNode* create_scalarized_object_description(AllocateNode *alloc, SafePointNode* sfpt);
|
||||
static bool can_eliminate_allocation(PhaseIterGVN *igvn, AllocateNode *alloc, GrowableArray <SafePointNode *> *safepoints);
|
||||
static bool can_eliminate_allocation(PhaseIterGVN* igvn, AllocateNode* alloc, Unique_Node_List* safepoints);
|
||||
|
||||
|
||||
PhaseIterGVN &igvn() const { return _igvn; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user