src/share/vm/opto/phaseX.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/phaseX.cpp Tue Nov 24 15:25:44 2015
--- new/src/share/vm/opto/phaseX.cpp Tue Nov 24 15:25:44 2015
*** 404,414 ****
--- 404,414 ----
//=============================================================================
//------------------------------PhaseRemoveUseless-----------------------------
// 1) Use a breadthfirst walk to collect useful nodes reachable from root.
! PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklist ) : Phase(Remove_Useless),
! PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN *gvn, Unique_Node_List *worklist, PhaseNumber phase_num) : Phase(phase_num),
_useful(Thread::current()->resource_area()) {
// Implementation requires 'UseLoopSafepoints == true' and an edge from root
// to each SafePointNode at a backward branch. Inserted in add_safepoint().
if( !UseLoopSafepoints || !OptoRemoveUseless ) return;
*** 441,450 ****
--- 441,535 ----
}
}
}
}
+ //=============================================================================
+ //------------------------------PhaseRenumberLive------------------------------
+ // First, remove useless nodes (equivalent to identifying live nodes).
+ // Then, renumber live nodes.
+ //
+ // The set of live nodes is returned by PhaseRemoveUseless in the _useful structure.
+ // If the number of live nodes is 'x' (where 'x' == _useful.size()), then the
+ // PhaseRenumberLive updates the node ID of each node (the _idx field) with a unique
+ // value in the range [0, x).
+ //
+ // At the end of the PhaseRenumberLive phase, the compiler's count of unique nodes is
+ // updated to 'x' and the list of dead nodes is reset (as there are no dead nodes).
+ //
+ // The PhaseRenumberLive phase updates two data structures with the new node IDs.
+ // (1) The worklist is used by the PhaseIterGVN phase to identify nodes that must be
+ // processed. The worklist is updated with the new node IDs.
+ // (2) Type information (the field PhaseGVN::_types) maps type information to each
+ // node ID. The mapping is updated to use the new node IDs as well.
+ //
+ // The PhaseRenumberLive phase does not preserve the order of elements in the worklist.
+ //
+ // Other data structures used by the compiler are not updated. The hash table for value
+ // numbering (the field PhaseGVN::_table) is not updated because computing the hash
+ // values is not based on node IDs. The field PhaseGVN::_nodes is not updated either
+ // because it is empty wherever PhaseRenumberLive is used.
+ PhaseRenumberLive::PhaseRenumberLive(PhaseGVN* gvn, Unique_Node_List* worklist, PhaseNumber phase_num) :
+ PhaseRemoveUseless(gvn, worklist, RenumberLiveNodes ? Renumber_Live : Remove_Useless) {
+
+ assert(C->live_nodes() == _useful.size(), "the number of live nodes must match the number of useful nodes");
+ uint old_unique_count = C->unique();
+ uint live_node_count = C->live_nodes();
+ uint worklist_size = worklist->size();
+
+ // Storage for the updated type information.
+ Type_Array new_type_array(Thread::current()->resource_area());
+
+ // Storage for holding the worklist with the updated IDs.
+ Unique_Node_List new_worklist(Thread::current()->resource_area());
+
+ // Process live nodes in the worklist.
+ uint current_idx = 0; // The current new node ID. Incremented after every assignment.
+ for (uint i = 0; i < _useful.size(); i++) {
+ Node* n = _useful.at(i);
+ const Type* type = gvn->type_or_null(n);
+ new_type_array.map(current_idx, type);
+
+ bool in_worklist = false;
+ if (worklist->member(n)) {
+ worklist->remove(n);
+ in_worklist = true;
+ }
+
+ n->set_idx(current_idx); // Update node ID.
+
+ if (in_worklist) {
+ new_worklist.push(n);
+ }
+
+ current_idx++;
+ }
+
+ assert(worklist->size() == 0, "original worklist must be empty");
+ assert(worklist_size == new_worklist.size(), "the new worklist must have the same size as the original worklist");
+ assert(live_node_count == current_idx, "all live nodes must be processed");
+
+ // Push nodes from the temporary worklist to the compiler's work
+ // list. The worklist usually contains only a few items (rarely
+ // more than 10), so pushing individual nodes does have a negligible
+ // effect on performance.
+ for (uint i = 0; i < worklist_size; i++) {
+ worklist->push(new_worklist.pop());
+ }
+
+ // Replace the compiler's type information with the updated type information.
+ // The number of nodes for which type information is stored can be large (up
+ // to several tens of thousands), therefore type information is updated with
+ // a memory copy.
+ gvn->types().replace_with(&new_type_array);
+
+ // Update the unique node count of the compilation to the number of currently live nodes.
+ C->set_unique(live_node_count);
+
+ // Set the dead node count to 0 and reset dead node list.
+ C->reset_dead_node_list();
+ }
//=============================================================================
//------------------------------PhaseTransform---------------------------------
PhaseTransform::PhaseTransform( PhaseNumber pnum ) : Phase(pnum),
_arena(Thread::current()->resource_area()),
*** 1913,1922 ****
--- 1998,2017 ----
while( i >= _max ) _max <<= 1; // Double to fit
_types = (const Type**)_a->Arealloc( _types, old*sizeof(Type*),_max*sizeof(Type*));
memset( &_types[old], 0, (_max-old)*sizeof(Type*) );
}
+ void Type_Array::replace_with(Type_Array* ta) {
+ assert(ta->Size() <= Size(), "size of current type must be larger than the size of the type copied in");
+ if (ta->Size() <= Size()) {
+ memcpy(_types, ta->_types, ta->_max * sizeof(Type*));
+ uint diff = Size() - ta->Size();
+ if (diff > 0) {
+ memset(&_types[ta->Size()], 0, diff * sizeof(Type*));
+ }
+ }
+ }
//------------------------------dump-------------------------------------------
#ifndef PRODUCT
void Type_Array::dump() const {
uint max = Size();
for( uint i = 0; i < max; i++ ) {
src/share/vm/opto/phaseX.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File