Mon, 27 Aug 2012 09:46:38 -0700
7148109: C2 compiler consumes too much heap resources
Summary: Add split_arena to allocate temporary arrays in PhaseChaitin::Split() and free them on method's exit.
Reviewed-by: twisti
1.1 --- a/src/share/vm/opto/chaitin.cpp Fri Aug 24 16:23:59 2012 -0700 1.2 +++ b/src/share/vm/opto/chaitin.cpp Mon Aug 27 09:46:38 2012 -0700 1.3 @@ -222,6 +222,7 @@ 1.4 _alternate = 0; 1.5 _matcher._allocation_started = true; 1.6 1.7 + ResourceArea split_arena; // Arena for Split local resources 1.8 ResourceArea live_arena; // Arena for liveness & IFG info 1.9 ResourceMark rm(&live_arena); 1.10 1.11 @@ -324,7 +325,7 @@ 1.12 // Bail out if unique gets too large (ie - unique > MaxNodeLimit) 1.13 C->check_node_count(10*must_spill, "out of nodes before split"); 1.14 if (C->failing()) return; 1.15 - _maxlrg = Split( _maxlrg ); // Split spilling LRG everywhere 1.16 + _maxlrg = Split(_maxlrg, &split_arena); // Split spilling LRG everywhere 1.17 // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) 1.18 // or we failed to split 1.19 C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after physical split"); 1.20 @@ -390,7 +391,7 @@ 1.21 } 1.22 1.23 if( !_maxlrg ) return; 1.24 - _maxlrg = Split( _maxlrg ); // Split spilling LRG everywhere 1.25 + _maxlrg = Split(_maxlrg, &split_arena); // Split spilling LRG everywhere 1.26 // Bail out if unique gets too large (ie - unique > MaxNodeLimit - 2*NodeLimitFudgeFactor) 1.27 C->check_node_count(2*NodeLimitFudgeFactor, "out of nodes after split"); 1.28 if (C->failing()) return;
2.1 --- a/src/share/vm/opto/chaitin.hpp Fri Aug 24 16:23:59 2012 -0700 2.2 +++ b/src/share/vm/opto/chaitin.hpp Mon Aug 27 09:46:38 2012 -0700 2.3 @@ -470,7 +470,7 @@ 2.4 2.5 // Split uncolorable live ranges 2.6 // Return new number of live ranges 2.7 - uint Split( uint maxlrg ); 2.8 + uint Split(uint maxlrg, ResourceArea* split_arena); 2.9 2.10 // Copy 'was_spilled'-edness from one Node to another. 2.11 void copy_was_spilled( Node *src, Node *dst );
3.1 --- a/src/share/vm/opto/reg_split.cpp Fri Aug 24 16:23:59 2012 -0700 3.2 +++ b/src/share/vm/opto/reg_split.cpp Mon Aug 27 09:46:38 2012 -0700 3.3 @@ -449,9 +449,12 @@ 3.4 // USES: If USE is in HRP, split at use to leave main LRG on stack. 3.5 // Else, hoist LRG back up to register only (ie - split is also DEF) 3.6 // We will compute a new maxlrg as we go 3.7 -uint PhaseChaitin::Split( uint maxlrg ) { 3.8 +uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { 3.9 NOT_PRODUCT( Compile::TracePhase t3("regAllocSplit", &_t_regAllocSplit, TimeCompiler); ) 3.10 3.11 + // Free thread local resources used by this method on exit. 3.12 + ResourceMark rm(split_arena); 3.13 + 3.14 uint bidx, pidx, slidx, insidx, inpidx, twoidx; 3.15 uint non_phi = 1, spill_cnt = 0; 3.16 Node **Reachblock; 3.17 @@ -461,14 +464,17 @@ 3.18 bool u1, u2, u3; 3.19 Block *b, *pred; 3.20 PhiNode *phi; 3.21 - GrowableArray<uint> lidxs; 3.22 + GrowableArray<uint> lidxs(split_arena, _maxlrg, 0, 0); 3.23 3.24 // Array of counters to count splits per live range 3.25 - GrowableArray<uint> splits; 3.26 + GrowableArray<uint> splits(split_arena, _maxlrg, 0, 0); 3.27 + 3.28 +#define NEW_SPLIT_ARRAY(type, size)\ 3.29 + (type*) split_arena->allocate_bytes((size) * sizeof(type)) 3.30 3.31 //----------Setup Code---------- 3.32 // Create a convenient mapping from lrg numbers to reaches/leaves indices 3.33 - uint *lrg2reach = NEW_RESOURCE_ARRAY( uint, _maxlrg ); 3.34 + uint *lrg2reach = NEW_SPLIT_ARRAY( uint, _maxlrg ); 3.35 // Keep track of DEFS & Phis for later passes 3.36 defs = new Node_List(); 3.37 phis = new Node_List(); 3.38 @@ -500,15 +506,15 @@ 3.39 // a Def is UP or DOWN. UP means that it should get a register (ie - 3.40 // it is always in LRP regions), and DOWN means that it is probably 3.41 // on the stack (ie - it crosses HRP regions). 3.42 - Node ***Reaches = NEW_RESOURCE_ARRAY( Node**, _cfg._num_blocks+1 ); 3.43 - bool **UP = NEW_RESOURCE_ARRAY( bool*, _cfg._num_blocks+1 ); 3.44 - Node **debug_defs = NEW_RESOURCE_ARRAY( Node*, spill_cnt ); 3.45 - VectorSet **UP_entry= NEW_RESOURCE_ARRAY( VectorSet*, spill_cnt ); 3.46 + Node ***Reaches = NEW_SPLIT_ARRAY( Node**, _cfg._num_blocks+1 ); 3.47 + bool **UP = NEW_SPLIT_ARRAY( bool*, _cfg._num_blocks+1 ); 3.48 + Node **debug_defs = NEW_SPLIT_ARRAY( Node*, spill_cnt ); 3.49 + VectorSet **UP_entry= NEW_SPLIT_ARRAY( VectorSet*, spill_cnt ); 3.50 3.51 // Initialize Reaches & UP 3.52 for( bidx = 0; bidx < _cfg._num_blocks+1; bidx++ ) { 3.53 - Reaches[bidx] = NEW_RESOURCE_ARRAY( Node*, spill_cnt ); 3.54 - UP[bidx] = NEW_RESOURCE_ARRAY( bool, spill_cnt ); 3.55 + Reaches[bidx] = NEW_SPLIT_ARRAY( Node*, spill_cnt ); 3.56 + UP[bidx] = NEW_SPLIT_ARRAY( bool, spill_cnt ); 3.57 Node **Reachblock = Reaches[bidx]; 3.58 bool *UPblock = UP[bidx]; 3.59 for( slidx = 0; slidx < spill_cnt; slidx++ ) { 3.60 @@ -517,9 +523,11 @@ 3.61 } 3.62 } 3.63 3.64 +#undef NEW_SPLIT_ARRAY 3.65 + 3.66 // Initialize to array of empty vectorsets 3.67 for( slidx = 0; slidx < spill_cnt; slidx++ ) 3.68 - UP_entry[slidx] = new VectorSet(Thread::current()->resource_area()); 3.69 + UP_entry[slidx] = new VectorSet(split_arena); 3.70 3.71 //----------PASS 1---------- 3.72 //----------Propagation & Node Insertion Code----------