6484959: G1: introduce survivor spaces

Fri, 06 Feb 2009 01:38:50 +0300

author
apetrusenko
date
Fri, 06 Feb 2009 01:38:50 +0300
changeset 980
58054a18d735
parent 979
82a980778b92
child 981
05c6d52fa7a9

6484959: G1: introduce survivor spaces
6797754: G1: combined bugfix
Summary: Implemented a policy to control G1 survivor space parameters.
Reviewed-by: tonyp, iveresov

src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1RemSet.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1_globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/heapRegion.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/survRateGroup.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/survRateGroup.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/includeDB_gc_g1 file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/ageTable.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/ageTable.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Feb 05 11:42:10 2009 -0800
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Feb 06 01:38:50 2009 +0300
     1.3 @@ -141,7 +141,7 @@
     1.4      _scan_only_head(NULL), _scan_only_tail(NULL), _curr_scan_only(NULL),
     1.5      _length(0), _scan_only_length(0),
     1.6      _last_sampled_rs_lengths(0),
     1.7 -    _survivor_head(NULL), _survivors_tail(NULL), _survivor_length(0)
     1.8 +    _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0)
     1.9  {
    1.10    guarantee( check_list_empty(false), "just making sure..." );
    1.11  }
    1.12 @@ -159,16 +159,15 @@
    1.13  }
    1.14  
    1.15  void YoungList::add_survivor_region(HeapRegion* hr) {
    1.16 -  assert(!hr->is_survivor(), "should not already be for survived");
    1.17 +  assert(hr->is_survivor(), "should be flagged as survivor region");
    1.18    assert(hr->get_next_young_region() == NULL, "cause it should!");
    1.19  
    1.20    hr->set_next_young_region(_survivor_head);
    1.21    if (_survivor_head == NULL) {
    1.22 -    _survivors_tail = hr;
    1.23 +    _survivor_tail = hr;
    1.24    }
    1.25    _survivor_head = hr;
    1.26  
    1.27 -  hr->set_survivor();
    1.28    ++_survivor_length;
    1.29  }
    1.30  
    1.31 @@ -239,7 +238,7 @@
    1.32  
    1.33    empty_list(_survivor_head);
    1.34    _survivor_head = NULL;
    1.35 -  _survivors_tail = NULL;
    1.36 +  _survivor_tail = NULL;
    1.37    _survivor_length = 0;
    1.38  
    1.39    _last_sampled_rs_lengths = 0;
    1.40 @@ -391,6 +390,7 @@
    1.41  
    1.42    // Add survivor regions to SurvRateGroup.
    1.43    _g1h->g1_policy()->note_start_adding_survivor_regions();
    1.44 +  _g1h->g1_policy()->finished_recalculating_age_indexes(true /* is_survivors */);
    1.45    for (HeapRegion* curr = _survivor_head;
    1.46         curr != NULL;
    1.47         curr = curr->get_next_young_region()) {
    1.48 @@ -401,7 +401,7 @@
    1.49    if (_survivor_head != NULL) {
    1.50      _head           = _survivor_head;
    1.51      _length         = _survivor_length + _scan_only_length;
    1.52 -    _survivors_tail->set_next_young_region(_scan_only_head);
    1.53 +    _survivor_tail->set_next_young_region(_scan_only_head);
    1.54    } else {
    1.55      _head           = _scan_only_head;
    1.56      _length         = _scan_only_length;
    1.57 @@ -418,9 +418,9 @@
    1.58    _curr_scan_only   = NULL;
    1.59  
    1.60    _survivor_head    = NULL;
    1.61 -  _survivors_tail   = NULL;
    1.62 +  _survivor_tail   = NULL;
    1.63    _survivor_length  = 0;
    1.64 -  _g1h->g1_policy()->finished_recalculating_age_indexes();
    1.65 +  _g1h->g1_policy()->finished_recalculating_age_indexes(false /* is_survivors */);
    1.66  
    1.67    assert(check_list_well_formed(), "young list should be well formed");
    1.68  }
    1.69 @@ -553,7 +553,7 @@
    1.70    if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) {
    1.71      alloc_region = newAllocRegion_work(word_size, true, zero_filled);
    1.72      if (purpose == GCAllocForSurvived && alloc_region != NULL) {
    1.73 -      _young_list->add_survivor_region(alloc_region);
    1.74 +      alloc_region->set_survivor();
    1.75      }
    1.76      ++_gc_alloc_region_counts[purpose];
    1.77    } else {
    1.78 @@ -2593,6 +2593,9 @@
    1.79          _young_list->print();
    1.80  #endif // SCAN_ONLY_VERBOSE
    1.81  
    1.82 +        g1_policy()->record_survivor_regions(_young_list->survivor_length(),
    1.83 +                                             _young_list->first_survivor_region(),
    1.84 +                                             _young_list->last_survivor_region());
    1.85          _young_list->reset_auxilary_lists();
    1.86        }
    1.87      } else {
    1.88 @@ -2619,7 +2622,9 @@
    1.89  #endif // SCAN_ONLY_VERBOSE
    1.90  
    1.91      double end_time_sec = os::elapsedTime();
    1.92 -    g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0);
    1.93 +    if (!evacuation_failed()) {
    1.94 +      g1_policy()->record_pause_time((end_time_sec - start_time_sec)*1000.0);
    1.95 +    }
    1.96      GCOverheadReporter::recordSTWEnd(end_time_sec);
    1.97      g1_policy()->record_collection_pause_end(popular_region != NULL,
    1.98                                               abandoned);
    1.99 @@ -2754,6 +2759,13 @@
   1.100      _gc_alloc_region_list = r->next_gc_alloc_region();
   1.101      r->set_next_gc_alloc_region(NULL);
   1.102      r->set_is_gc_alloc_region(false);
   1.103 +    if (r->is_survivor()) {
   1.104 +      if (r->is_empty()) {
   1.105 +        r->set_not_young();
   1.106 +      } else {
   1.107 +        _young_list->add_survivor_region(r);
   1.108 +      }
   1.109 +    }
   1.110      if (r->is_empty()) {
   1.111        ++_free_regions;
   1.112      }
   1.113 @@ -3150,6 +3162,20 @@
   1.114    return block;
   1.115  }
   1.116  
   1.117 +void G1CollectedHeap::retire_alloc_region(HeapRegion* alloc_region,
   1.118 +                                            bool par) {
   1.119 +  // Another thread might have obtained alloc_region for the given
   1.120 +  // purpose, and might be attempting to allocate in it, and might
   1.121 +  // succeed.  Therefore, we can't do the "finalization" stuff on the
   1.122 +  // region below until we're sure the last allocation has happened.
   1.123 +  // We ensure this by allocating the remaining space with a garbage
   1.124 +  // object.
   1.125 +  if (par) par_allocate_remaining_space(alloc_region);
   1.126 +  // Now we can do the post-GC stuff on the region.
   1.127 +  alloc_region->note_end_of_copying();
   1.128 +  g1_policy()->record_after_bytes(alloc_region->used());
   1.129 +}
   1.130 +
   1.131  HeapWord*
   1.132  G1CollectedHeap::allocate_during_gc_slow(GCAllocPurpose purpose,
   1.133                                           HeapRegion*    alloc_region,
   1.134 @@ -3167,16 +3193,7 @@
   1.135      // Otherwise, continue; this new region is empty, too.
   1.136    }
   1.137    assert(alloc_region != NULL, "We better have an allocation region");
   1.138 -  // Another thread might have obtained alloc_region for the given
   1.139 -  // purpose, and might be attempting to allocate in it, and might
   1.140 -  // succeed.  Therefore, we can't do the "finalization" stuff on the
   1.141 -  // region below until we're sure the last allocation has happened.
   1.142 -  // We ensure this by allocating the remaining space with a garbage
   1.143 -  // object.
   1.144 -  if (par) par_allocate_remaining_space(alloc_region);
   1.145 -  // Now we can do the post-GC stuff on the region.
   1.146 -  alloc_region->note_end_of_copying();
   1.147 -  g1_policy()->record_after_bytes(alloc_region->used());
   1.148 +  retire_alloc_region(alloc_region, par);
   1.149  
   1.150    if (_gc_alloc_region_counts[purpose] >= g1_policy()->max_regions(purpose)) {
   1.151      // Cannot allocate more regions for the given purpose.
   1.152 @@ -3185,7 +3202,7 @@
   1.153      if (purpose != alt_purpose) {
   1.154        HeapRegion* alt_region = _gc_alloc_regions[alt_purpose];
   1.155        // Has not the alternative region been aliased?
   1.156 -      if (alloc_region != alt_region) {
   1.157 +      if (alloc_region != alt_region && alt_region != NULL) {
   1.158          // Try to allocate in the alternative region.
   1.159          if (par) {
   1.160            block = alt_region->par_allocate(word_size);
   1.161 @@ -3194,9 +3211,10 @@
   1.162          }
   1.163          // Make an alias.
   1.164          _gc_alloc_regions[purpose] = _gc_alloc_regions[alt_purpose];
   1.165 -      }
   1.166 -      if (block != NULL) {
   1.167 -        return block;
   1.168 +        if (block != NULL) {
   1.169 +          return block;
   1.170 +        }
   1.171 +        retire_alloc_region(alt_region, par);
   1.172        }
   1.173        // Both the allocation region and the alternative one are full
   1.174        // and aliased, replace them with a new allocation region.
   1.175 @@ -3497,6 +3515,7 @@
   1.176    OverflowQueue* _overflowed_refs;
   1.177  
   1.178    G1ParGCAllocBuffer _alloc_buffers[GCAllocPurposeCount];
   1.179 +  ageTable           _age_table;
   1.180  
   1.181    size_t           _alloc_buffer_waste;
   1.182    size_t           _undo_waste;
   1.183 @@ -3538,6 +3557,7 @@
   1.184        _refs(g1h->task_queue(queue_num)),
   1.185        _hash_seed(17), _queue_num(queue_num),
   1.186        _term_attempts(0),
   1.187 +      _age_table(false),
   1.188  #if G1_DETAILED_STATS
   1.189        _pushes(0), _pops(0), _steals(0),
   1.190        _steal_attempts(0),  _overflow_pushes(0),
   1.191 @@ -3572,8 +3592,9 @@
   1.192  
   1.193    RefToScanQueue*   refs()            { return _refs;             }
   1.194    OverflowQueue*    overflowed_refs() { return _overflowed_refs;  }
   1.195 -
   1.196 -  inline G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
   1.197 +  ageTable*         age_table()       { return &_age_table;       }
   1.198 +
   1.199 +  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
   1.200      return &_alloc_buffers[purpose];
   1.201    }
   1.202  
   1.203 @@ -3834,7 +3855,9 @@
   1.204            (!from_region->is_young() && young_index == 0), "invariant" );
   1.205    G1CollectorPolicy* g1p = _g1->g1_policy();
   1.206    markOop m = old->mark();
   1.207 -  GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, m->age(),
   1.208 +  int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age()
   1.209 +                                           : m->age();
   1.210 +  GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age,
   1.211                                                               word_sz);
   1.212    HeapWord* obj_ptr = _par_scan_state->allocate(alloc_purpose, word_sz);
   1.213    oop       obj     = oop(obj_ptr);
   1.214 @@ -3872,9 +3895,12 @@
   1.215          obj->incr_age();
   1.216        } else {
   1.217          m = m->incr_age();
   1.218 +        obj->set_mark(m);
   1.219        }
   1.220 +      _par_scan_state->age_table()->add(obj, word_sz);
   1.221 +    } else {
   1.222 +      obj->set_mark(m);
   1.223      }
   1.224 -    obj->set_mark(m);
   1.225  
   1.226      // preserve "next" mark bit
   1.227      if (_g1->mark_in_progress() && !_g1->is_obj_ill(old)) {
   1.228 @@ -4129,6 +4155,9 @@
   1.229        _g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
   1.230        _g1h->g1_policy()->record_termination_time(i, term_ms);
   1.231      }
   1.232 +    if (G1UseSurvivorSpace) {
   1.233 +      _g1h->g1_policy()->record_thread_age_table(pss.age_table());
   1.234 +    }
   1.235      _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
   1.236  
   1.237      // Clean up any par-expanded rem sets.
   1.238 @@ -4368,7 +4397,7 @@
   1.239    // Is this the right thing to do here?  We don't save marks
   1.240    // on individual heap regions when we allocate from
   1.241    // them in parallel, so this seems like the correct place for this.
   1.242 -  all_alloc_regions_note_end_of_copying();
   1.243 +  retire_all_alloc_regions();
   1.244    {
   1.245      G1IsAliveClosure is_alive(this);
   1.246      G1KeepAliveClosure keep_alive(this);
   1.247 @@ -5008,7 +5037,7 @@
   1.248    return no_allocs;
   1.249  }
   1.250  
   1.251 -void G1CollectedHeap::all_alloc_regions_note_end_of_copying() {
   1.252 +void G1CollectedHeap::retire_all_alloc_regions() {
   1.253    for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
   1.254      HeapRegion* r = _gc_alloc_regions[ap];
   1.255      if (r != NULL) {
   1.256 @@ -5021,8 +5050,7 @@
   1.257          }
   1.258        }
   1.259        if (!has_processed_alias) {
   1.260 -        r->note_end_of_copying();
   1.261 -        g1_policy()->record_after_bytes(r->used());
   1.262 +        retire_alloc_region(r, false /* par */);
   1.263        }
   1.264      }
   1.265    }
     2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Thu Feb 05 11:42:10 2009 -0800
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Feb 06 01:38:50 2009 +0300
     2.3 @@ -90,7 +90,7 @@
     2.4    HeapRegion* _curr_scan_only;
     2.5  
     2.6    HeapRegion* _survivor_head;
     2.7 -  HeapRegion* _survivors_tail;
     2.8 +  HeapRegion* _survivor_tail;
     2.9    size_t      _survivor_length;
    2.10  
    2.11    void          empty_list(HeapRegion* list);
    2.12 @@ -105,6 +105,7 @@
    2.13    bool          is_empty() { return _length == 0; }
    2.14    size_t        length() { return _length; }
    2.15    size_t        scan_only_length() { return _scan_only_length; }
    2.16 +  size_t        survivor_length() { return _survivor_length; }
    2.17  
    2.18    void rs_length_sampling_init();
    2.19    bool rs_length_sampling_more();
    2.20 @@ -120,6 +121,7 @@
    2.21    HeapRegion* first_region() { return _head; }
    2.22    HeapRegion* first_scan_only_region() { return _scan_only_head; }
    2.23    HeapRegion* first_survivor_region() { return _survivor_head; }
    2.24 +  HeapRegion* last_survivor_region() { return _survivor_tail; }
    2.25    HeapRegion* par_get_next_scan_only_region() {
    2.26      MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
    2.27      HeapRegion* ret = _curr_scan_only;
    2.28 @@ -219,7 +221,7 @@
    2.29    // The to-space memory regions into which objects are being copied during
    2.30    // a GC.
    2.31    HeapRegion* _gc_alloc_regions[GCAllocPurposeCount];
    2.32 -  uint _gc_alloc_region_counts[GCAllocPurposeCount];
    2.33 +  size_t _gc_alloc_region_counts[GCAllocPurposeCount];
    2.34  
    2.35    // A list of the regions that have been set to be alloc regions in the
    2.36    // current collection.
    2.37 @@ -281,8 +283,8 @@
    2.38    // Returns "true" iff none of the gc alloc regions have any allocations
    2.39    // since the last call to "save_marks".
    2.40    bool all_alloc_regions_no_allocs_since_save_marks();
    2.41 -  // Calls "note_end_of_copying on all gc alloc_regions.
    2.42 -  void all_alloc_regions_note_end_of_copying();
    2.43 +  // Perform finalization stuff on all allocation regions.
    2.44 +  void retire_all_alloc_regions();
    2.45  
    2.46    // The number of regions allocated to hold humongous objects.
    2.47    int         _num_humongous_regions;
    2.48 @@ -351,6 +353,10 @@
    2.49    // that parallel threads might be attempting allocations.
    2.50    void par_allocate_remaining_space(HeapRegion* r);
    2.51  
    2.52 +  // Retires an allocation region when it is full or at the end of a
    2.53 +  // GC pause.
    2.54 +  void  retire_alloc_region(HeapRegion* alloc_region, bool par);
    2.55 +
    2.56    // Helper function for two callbacks below.
    2.57    // "full", if true, indicates that the GC is for a System.gc() request,
    2.58    // and should collect the entire heap.  If "clear_all_soft_refs" is true,
     3.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Thu Feb 05 11:42:10 2009 -0800
     3.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Feb 06 01:38:50 2009 +0300
     3.3 @@ -196,8 +196,13 @@
     3.4    _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived",
     3.5                                                   G1YoungSurvRateNumRegionsSummary)),
     3.6    _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor",
     3.7 -                                              G1YoungSurvRateNumRegionsSummary))
     3.8 +                                              G1YoungSurvRateNumRegionsSummary)),
     3.9    // add here any more surv rate groups
    3.10 +  _recorded_survivor_regions(0),
    3.11 +  _recorded_survivor_head(NULL),
    3.12 +  _recorded_survivor_tail(NULL),
    3.13 +  _survivors_age_table(true)
    3.14 +
    3.15  {
    3.16    _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
    3.17    _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
    3.18 @@ -272,6 +277,15 @@
    3.19    _concurrent_mark_cleanup_times_ms->add(0.20);
    3.20    _tenuring_threshold = MaxTenuringThreshold;
    3.21  
    3.22 +  if (G1UseSurvivorSpace) {
    3.23 +    // if G1FixedSurvivorSpaceSize is 0 which means the size is not
    3.24 +    // fixed, then _max_survivor_regions will be calculated at
    3.25 +    // calculate_young_list_target_config diring initialization
    3.26 +    _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes;
    3.27 +  } else {
    3.28 +    _max_survivor_regions = 0;
    3.29 +  }
    3.30 +
    3.31    initialize_all();
    3.32  }
    3.33  
    3.34 @@ -301,6 +315,8 @@
    3.35                                    "-XX:+UseConcMarkSweepGC.");
    3.36    }
    3.37  
    3.38 +  initialize_gc_policy_counters();
    3.39 +
    3.40    if (G1Gen) {
    3.41      _in_young_gc_mode = true;
    3.42  
    3.43 @@ -322,6 +338,12 @@
    3.44    }
    3.45  }
    3.46  
    3.47 +// Create the jstat counters for the policy.
    3.48 +void G1CollectorPolicy::initialize_gc_policy_counters()
    3.49 +{
    3.50 +  _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 2 + G1Gen);
    3.51 +}
    3.52 +
    3.53  void G1CollectorPolicy::calculate_young_list_min_length() {
    3.54    _young_list_min_length = 0;
    3.55  
    3.56 @@ -352,6 +374,7 @@
    3.57      guarantee( so_length < _young_list_target_length, "invariant" );
    3.58      _young_list_so_prefix_length = so_length;
    3.59    }
    3.60 +  calculate_survivors_policy();
    3.61  }
    3.62  
    3.63  // This method calculate the optimal scan-only set for a fixed young
    3.64 @@ -448,6 +471,9 @@
    3.65    if (full_young_gcs() && _free_regions_at_end_of_collection > 0) {
    3.66      // we are in fully-young mode and there are free regions in the heap
    3.67  
    3.68 +    double survivor_regions_evac_time =
    3.69 +        predict_survivor_regions_evac_time();
    3.70 +
    3.71      size_t min_so_length = 0;
    3.72      size_t max_so_length = 0;
    3.73  
    3.74 @@ -497,9 +523,8 @@
    3.75        scanned_cards = predict_non_young_card_num(adj_rs_lengths);
    3.76      // calculate this once, so that we don't have to recalculate it in
    3.77      // the innermost loop
    3.78 -    double base_time_ms = predict_base_elapsed_time_ms(pending_cards,
    3.79 -                                                       scanned_cards);
    3.80 -
    3.81 +    double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards)
    3.82 +                          + survivor_regions_evac_time;
    3.83      // the result
    3.84      size_t final_young_length = 0;
    3.85      size_t final_so_length = 0;
    3.86 @@ -548,14 +573,14 @@
    3.87      bool done = false;
    3.88      // this is the outermost loop
    3.89      while (!done) {
    3.90 -#if 0
    3.91 +#ifdef TRACE_CALC_YOUNG_CONFIG
    3.92        // leave this in for debugging, just in case
    3.93        gclog_or_tty->print_cr("searching between " SIZE_FORMAT " and " SIZE_FORMAT
    3.94                               ", incr " SIZE_FORMAT ", pass %s",
    3.95                               from_so_length, to_so_length, so_length_incr,
    3.96                               (pass == pass_type_coarse) ? "coarse" :
    3.97                               (pass == pass_type_fine) ? "fine" : "final");
    3.98 -#endif // 0
    3.99 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.100  
   3.101        size_t so_length = from_so_length;
   3.102        size_t init_free_regions =
   3.103 @@ -651,11 +676,11 @@
   3.104            guarantee( so_length_incr == so_coarse_increments, "invariant" );
   3.105            guarantee( final_so_length >= min_so_length, "invariant" );
   3.106  
   3.107 -#if 0
   3.108 +#ifdef TRACE_CALC_YOUNG_CONFIG
   3.109            // leave this in for debugging, just in case
   3.110            gclog_or_tty->print_cr("  coarse pass: SO length " SIZE_FORMAT,
   3.111                                   final_so_length);
   3.112 -#endif // 0
   3.113 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.114  
   3.115            from_so_length =
   3.116              (final_so_length - min_so_length > so_coarse_increments) ?
   3.117 @@ -687,12 +712,12 @@
   3.118              // of the optimal
   3.119              size_t new_so_length = 950 * final_so_length / 1000;
   3.120  
   3.121 -#if 0
   3.122 +#ifdef TRACE_CALC_YOUNG_CONFIG
   3.123              // leave this in for debugging, just in case
   3.124              gclog_or_tty->print_cr("  fine pass: SO length " SIZE_FORMAT
   3.125                                     ", setting it to " SIZE_FORMAT,
   3.126                                      final_so_length, new_so_length);
   3.127 -#endif // 0
   3.128 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.129  
   3.130              from_so_length = new_so_length;
   3.131              to_so_length = new_so_length;
   3.132 @@ -719,7 +744,8 @@
   3.133      }
   3.134  
   3.135      // we should have at least one region in the target young length
   3.136 -    _young_list_target_length = MAX2((size_t) 1, final_young_length);
   3.137 +    _young_list_target_length =
   3.138 +        MAX2((size_t) 1, final_young_length + _recorded_survivor_regions);
   3.139      if (final_so_length >= final_young_length)
   3.140        // and we need to ensure that the S-O length is not greater than
   3.141        // the target young length (this is being a bit careful)
   3.142 @@ -734,7 +760,7 @@
   3.143      double end_time_sec = os::elapsedTime();
   3.144      double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0;
   3.145  
   3.146 -#if 0
   3.147 +#ifdef TRACE_CALC_YOUNG_CONFIG
   3.148      // leave this in for debugging, just in case
   3.149      gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT
   3.150                             ", SO = " SIZE_FORMAT ", "
   3.151 @@ -747,9 +773,9 @@
   3.152                             calculations,
   3.153                             full_young_gcs() ? "full" : "partial",
   3.154                             should_initiate_conc_mark() ? " i-m" : "",
   3.155 -                           in_marking_window(),
   3.156 -                           in_marking_window_im());
   3.157 -#endif // 0
   3.158 +                           _in_marking_window,
   3.159 +                           _in_marking_window_im);
   3.160 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.161  
   3.162      if (_young_list_target_length < _young_list_min_length) {
   3.163        // bummer; this means that, if we do a pause when the optimal
   3.164 @@ -768,14 +794,14 @@
   3.165          // S-O length
   3.166          so_length = calculate_optimal_so_length(_young_list_min_length);
   3.167  
   3.168 -#if 0
   3.169 +#ifdef TRACE_CALC_YOUNG_CONFIG
   3.170        // leave this in for debugging, just in case
   3.171        gclog_or_tty->print_cr("adjusted target length from "
   3.172                               SIZE_FORMAT " to " SIZE_FORMAT
   3.173                               ", SO " SIZE_FORMAT,
   3.174                               _young_list_target_length, _young_list_min_length,
   3.175                               so_length);
   3.176 -#endif // 0
   3.177 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.178  
   3.179        _young_list_target_length =
   3.180          MAX2(_young_list_min_length, (size_t)1);
   3.181 @@ -785,12 +811,12 @@
   3.182      // we are in a partially-young mode or we've run out of regions (due
   3.183      // to evacuation failure)
   3.184  
   3.185 -#if 0
   3.186 +#ifdef TRACE_CALC_YOUNG_CONFIG
   3.187      // leave this in for debugging, just in case
   3.188      gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT
   3.189                             ", SO " SIZE_FORMAT,
   3.190                             _young_list_min_length, 0);
   3.191 -#endif // 0
   3.192 +#endif // TRACE_CALC_YOUNG_CONFIG
   3.193  
   3.194      // we'll do the pause as soon as possible and with no S-O prefix
   3.195      // (see above for the reasons behind the latter)
   3.196 @@ -884,6 +910,16 @@
   3.197    return true;
   3.198  }
   3.199  
   3.200 +double G1CollectorPolicy::predict_survivor_regions_evac_time() {
   3.201 +  double survivor_regions_evac_time = 0.0;
   3.202 +  for (HeapRegion * r = _recorded_survivor_head;
   3.203 +       r != NULL && r != _recorded_survivor_tail->get_next_young_region();
   3.204 +       r = r->get_next_young_region()) {
   3.205 +    survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true);
   3.206 +  }
   3.207 +  return survivor_regions_evac_time;
   3.208 +}
   3.209 +
   3.210  void G1CollectorPolicy::check_prediction_validity() {
   3.211    guarantee( adaptive_young_list_length(), "should not call this otherwise" );
   3.212  
   3.213 @@ -995,11 +1031,15 @@
   3.214    _short_lived_surv_rate_group->start_adding_regions();
   3.215    // also call this on any additional surv rate groups
   3.216  
   3.217 +  record_survivor_regions(0, NULL, NULL);
   3.218 +
   3.219    _prev_region_num_young   = _region_num_young;
   3.220    _prev_region_num_tenured = _region_num_tenured;
   3.221  
   3.222    _free_regions_at_end_of_collection = _g1->free_regions();
   3.223    _scan_only_regions_at_end_of_collection = 0;
   3.224 +  // Reset survivors SurvRateGroup.
   3.225 +  _survivor_surv_rate_group->reset();
   3.226    calculate_young_list_min_length();
   3.227    calculate_young_list_target_config();
   3.228   }
   3.229 @@ -1104,6 +1144,10 @@
   3.230    _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length);
   3.231    tag_scan_only(short_lived_so_length);
   3.232  
   3.233 +  if (G1UseSurvivorSpace) {
   3.234 +    _survivors_age_table.clear();
   3.235 +  }
   3.236 +
   3.237    assert( verify_young_ages(), "region age verification" );
   3.238  }
   3.239  
   3.240 @@ -1965,9 +2009,6 @@
   3.241    // </NEW PREDICTION>
   3.242  
   3.243    _target_pause_time_ms = -1.0;
   3.244 -
   3.245 -  // TODO: calculate tenuring threshold
   3.246 -  _tenuring_threshold = MaxTenuringThreshold;
   3.247  }
   3.248  
   3.249  // <NEW PREDICTION>
   3.250 @@ -2058,7 +2099,7 @@
   3.251      guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1,
   3.252                 "invariant" );
   3.253      int age = hr->age_in_surv_rate_group();
   3.254 -    double yg_surv_rate = predict_yg_surv_rate(age);
   3.255 +    double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group());
   3.256      bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate);
   3.257    }
   3.258  
   3.259 @@ -2091,7 +2132,7 @@
   3.260    }
   3.261  #if PREDICTIONS_VERBOSE
   3.262    if (young) {
   3.263 -    _recorded_young_bytes += hr->asSpace()->used();
   3.264 +    _recorded_young_bytes += hr->used();
   3.265    } else {
   3.266      _recorded_marked_bytes += hr->max_live_bytes();
   3.267    }
   3.268 @@ -2119,11 +2160,6 @@
   3.269        predict_non_young_card_num(_predicted_rs_lengths);
   3.270    _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions;
   3.271  
   3.272 -  _predicted_young_survival_ratio = 0.0;
   3.273 -  for (int i = 0; i < _recorded_young_regions; ++i)
   3.274 -    _predicted_young_survival_ratio += predict_yg_surv_rate(i);
   3.275 -  _predicted_young_survival_ratio /= (double) _recorded_young_regions;
   3.276 -
   3.277    _predicted_scan_only_scan_time_ms =
   3.278      predict_scan_only_time_ms(_recorded_scan_only_regions);
   3.279    _predicted_rs_update_time_ms =
   3.280 @@ -2673,8 +2709,11 @@
   3.281    assert(in_young_gc_mode(), "should be in young GC mode");
   3.282    bool ret;
   3.283    size_t young_list_length = _g1->young_list_length();
   3.284 -
   3.285 -  if (young_list_length < _young_list_target_length) {
   3.286 +  size_t young_list_max_length = _young_list_target_length;
   3.287 +  if (G1FixedEdenSize) {
   3.288 +    young_list_max_length -= _max_survivor_regions;
   3.289 +  }
   3.290 +  if (young_list_length < young_list_max_length) {
   3.291      ret = true;
   3.292      ++_region_num_young;
   3.293    } else {
   3.294 @@ -2710,17 +2749,39 @@
   3.295  }
   3.296  
   3.297  
   3.298 -uint G1CollectorPolicy::max_regions(int purpose) {
   3.299 +size_t G1CollectorPolicy::max_regions(int purpose) {
   3.300    switch (purpose) {
   3.301      case GCAllocForSurvived:
   3.302 -      return G1MaxSurvivorRegions;
   3.303 +      return _max_survivor_regions;
   3.304      case GCAllocForTenured:
   3.305 -      return UINT_MAX;
   3.306 +      return REGIONS_UNLIMITED;
   3.307      default:
   3.308 -      return UINT_MAX;
   3.309 +      ShouldNotReachHere();
   3.310 +      return REGIONS_UNLIMITED;
   3.311    };
   3.312  }
   3.313  
   3.314 +// Calculates survivor space parameters.
   3.315 +void G1CollectorPolicy::calculate_survivors_policy()
   3.316 +{
   3.317 +  if (!G1UseSurvivorSpace) {
   3.318 +    return;
   3.319 +  }
   3.320 +  if (G1FixedSurvivorSpaceSize == 0) {
   3.321 +    _max_survivor_regions = _young_list_target_length / SurvivorRatio;
   3.322 +  } else {
   3.323 +    _max_survivor_regions = G1FixedSurvivorSpaceSize;
   3.324 +  }
   3.325 +
   3.326 +  if (G1FixedTenuringThreshold) {
   3.327 +    _tenuring_threshold = MaxTenuringThreshold;
   3.328 +  } else {
   3.329 +    _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold(
   3.330 +        HeapRegion::GrainWords * _max_survivor_regions);
   3.331 +  }
   3.332 +}
   3.333 +
   3.334 +
   3.335  void
   3.336  G1CollectorPolicy_BestRegionsFirst::
   3.337  set_single_region_collection_set(HeapRegion* hr) {
   3.338 @@ -2743,7 +2804,11 @@
   3.339    double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
   3.340  
   3.341    size_t young_list_length = _g1->young_list_length();
   3.342 -  bool reached_target_length = young_list_length >= _young_list_target_length;
   3.343 +  size_t young_list_max_length = _young_list_target_length;
   3.344 +  if (G1FixedEdenSize) {
   3.345 +    young_list_max_length -= _max_survivor_regions;
   3.346 +  }
   3.347 +  bool reached_target_length = young_list_length >= young_list_max_length;
   3.348  
   3.349    if (in_young_gc_mode()) {
   3.350      if (reached_target_length) {
     4.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Thu Feb 05 11:42:10 2009 -0800
     4.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Fri Feb 06 01:38:50 2009 +0300
     4.3 @@ -557,6 +557,8 @@
     4.4      return get_new_neg_prediction(_young_gc_eff_seq);
     4.5    }
     4.6  
     4.7 +  double predict_survivor_regions_evac_time();
     4.8 +
     4.9    // </NEW PREDICTION>
    4.10  
    4.11  public:
    4.12 @@ -599,8 +601,8 @@
    4.13  
    4.14    // Returns an estimate of the survival rate of the region at yg-age
    4.15    // "yg_age".
    4.16 -  double predict_yg_surv_rate(int age) {
    4.17 -    TruncatedSeq* seq = _short_lived_surv_rate_group->get_seq(age);
    4.18 +  double predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) {
    4.19 +    TruncatedSeq* seq = surv_rate_group->get_seq(age);
    4.20      if (seq->num() == 0)
    4.21        gclog_or_tty->print("BARF! age is %d", age);
    4.22      guarantee( seq->num() > 0, "invariant" );
    4.23 @@ -610,6 +612,10 @@
    4.24      return pred;
    4.25    }
    4.26  
    4.27 +  double predict_yg_surv_rate(int age) {
    4.28 +    return predict_yg_surv_rate(age, _short_lived_surv_rate_group);
    4.29 +  }
    4.30 +
    4.31    double accum_yg_surv_rate_pred(int age) {
    4.32      return _short_lived_surv_rate_group->accum_surv_rate_pred(age);
    4.33    }
    4.34 @@ -822,6 +828,9 @@
    4.35  
    4.36    virtual void init();
    4.37  
    4.38 +  // Create jstat counters for the policy.
    4.39 +  virtual void initialize_gc_policy_counters();
    4.40 +
    4.41    virtual HeapWord* mem_allocate_work(size_t size,
    4.42                                        bool is_tlab,
    4.43                                        bool* gc_overhead_limit_was_exceeded);
    4.44 @@ -1047,8 +1056,12 @@
    4.45    // Print stats on young survival ratio
    4.46    void print_yg_surv_rate_info() const;
    4.47  
    4.48 -  void finished_recalculating_age_indexes() {
    4.49 -    _short_lived_surv_rate_group->finished_recalculating_age_indexes();
    4.50 +  void finished_recalculating_age_indexes(bool is_survivors) {
    4.51 +    if (is_survivors) {
    4.52 +      _survivor_surv_rate_group->finished_recalculating_age_indexes();
    4.53 +    } else {
    4.54 +      _short_lived_surv_rate_group->finished_recalculating_age_indexes();
    4.55 +    }
    4.56      // do that for any other surv rate groups
    4.57    }
    4.58  
    4.59 @@ -1097,6 +1110,17 @@
    4.60    // maximum amount of suvivors regions.
    4.61    int _tenuring_threshold;
    4.62  
    4.63 +  // The limit on the number of regions allocated for survivors.
    4.64 +  size_t _max_survivor_regions;
    4.65 +
    4.66 +  // The amount of survor regions after a collection.
    4.67 +  size_t _recorded_survivor_regions;
    4.68 +  // List of survivor regions.
    4.69 +  HeapRegion* _recorded_survivor_head;
    4.70 +  HeapRegion* _recorded_survivor_tail;
    4.71 +
    4.72 +  ageTable _survivors_age_table;
    4.73 +
    4.74  public:
    4.75  
    4.76    inline GCAllocPurpose
    4.77 @@ -1116,7 +1140,9 @@
    4.78      return GCAllocForTenured;
    4.79    }
    4.80  
    4.81 -  uint max_regions(int purpose);
    4.82 +  static const size_t REGIONS_UNLIMITED = ~(size_t)0;
    4.83 +
    4.84 +  size_t max_regions(int purpose);
    4.85  
    4.86    // The limit on regions for a particular purpose is reached.
    4.87    void note_alloc_region_limit_reached(int purpose) {
    4.88 @@ -1132,6 +1158,23 @@
    4.89    void note_stop_adding_survivor_regions() {
    4.90      _survivor_surv_rate_group->stop_adding_regions();
    4.91    }
    4.92 +
    4.93 +  void record_survivor_regions(size_t      regions,
    4.94 +                               HeapRegion* head,
    4.95 +                               HeapRegion* tail) {
    4.96 +    _recorded_survivor_regions = regions;
    4.97 +    _recorded_survivor_head    = head;
    4.98 +    _recorded_survivor_tail    = tail;
    4.99 +  }
   4.100 +
   4.101 +  void record_thread_age_table(ageTable* age_table)
   4.102 +  {
   4.103 +    _survivors_age_table.merge_par(age_table);
   4.104 +  }
   4.105 +
   4.106 +  // Calculates survivor space parameters.
   4.107 +  void calculate_survivors_policy();
   4.108 +
   4.109  };
   4.110  
   4.111  // This encapsulates a particular strategy for a g1 Collector.
     5.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Thu Feb 05 11:42:10 2009 -0800
     5.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Feb 06 01:38:50 2009 +0300
     5.3 @@ -572,6 +572,9 @@
     5.4    }
     5.5    guarantee( _cards_scanned == NULL, "invariant" );
     5.6    _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers());
     5.7 +  for (uint i = 0; i < n_workers(); ++i) {
     5.8 +    _cards_scanned[i] = 0;
     5.9 +  }
    5.10    _total_cards_scanned = 0;
    5.11  }
    5.12  
     6.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Thu Feb 05 11:42:10 2009 -0800
     6.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Feb 06 01:38:50 2009 +0300
     6.3 @@ -281,7 +281,17 @@
     6.4    develop(bool, G1HRRSFlushLogBuffersOnVerify, false,                       \
     6.5            "Forces flushing of log buffers before verification.")            \
     6.6                                                                              \
     6.7 -  product(intx, G1MaxSurvivorRegions, 0,                                    \
     6.8 -          "The maximum number of survivor regions")
     6.9 +  product(bool, G1UseSurvivorSpace, true,                                   \
    6.10 +          "When true, use survivor space.")                                 \
    6.11 +                                                                            \
    6.12 +  product(bool, G1FixedTenuringThreshold, false,                            \
    6.13 +          "When set, G1 will not adjust the tenuring threshold")            \
    6.14 +                                                                            \
    6.15 +  product(bool, G1FixedEdenSize, false,                                     \
    6.16 +          "When set, G1 will not allocate unused survivor space regions")   \
    6.17 +                                                                            \
    6.18 +  product(uintx, G1FixedSurvivorSpaceSize, 0,                               \
    6.19 +          "If non-0 is the size of the G1 survivor space, "                 \
    6.20 +          "otherwise SurvivorRatio is used to determine the size")
    6.21  
    6.22  G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
     7.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Thu Feb 05 11:42:10 2009 -0800
     7.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Fri Feb 06 01:38:50 2009 +0300
     7.3 @@ -566,7 +566,11 @@
     7.4    void note_end_of_copying() {
     7.5      assert(top() >= _next_top_at_mark_start,
     7.6             "Increase only");
     7.7 -    _next_top_at_mark_start = top();
     7.8 +    // Survivor regions will be scanned on the start of concurrent
     7.9 +    // marking.
    7.10 +    if (!is_survivor()) {
    7.11 +      _next_top_at_mark_start = top();
    7.12 +    }
    7.13    }
    7.14  
    7.15    // Returns "false" iff no object in the region was allocated when the
     8.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Thu Feb 05 11:42:10 2009 -0800
     8.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Feb 06 01:38:50 2009 +0300
     8.3 @@ -65,9 +65,11 @@
     8.4    // We need access in order to union things into the base table.
     8.5    BitMap* bm() { return &_bm; }
     8.6  
     8.7 +#if PRT_COUNT_OCCUPIED
     8.8    void recount_occupied() {
     8.9      _occupied = (jint) bm()->count_one_bits();
    8.10    }
    8.11 +#endif
    8.12  
    8.13    PerRegionTable(HeapRegion* hr) :
    8.14      _hr(hr),
    8.15 @@ -1144,7 +1146,9 @@
    8.16    size_t i = _outgoing_region_map.get_next_one_offset(0);
    8.17    while (i < _outgoing_region_map.size()) {
    8.18      HeapRegion* to_region = g1h->region_at(i);
    8.19 -    to_region->rem_set()->clear_incoming_entry(hr());
    8.20 +    if (!to_region->in_collection_set()) {
    8.21 +      to_region->rem_set()->clear_incoming_entry(hr());
    8.22 +    }
    8.23      i = _outgoing_region_map.get_next_one_offset(i+1);
    8.24    }
    8.25  }
     9.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Thu Feb 05 11:42:10 2009 -0800
     9.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.cpp	Fri Feb 06 01:38:50 2009 +0300
     9.3 @@ -29,23 +29,14 @@
     9.4                               const char* name,
     9.5                               size_t summary_surv_rates_len) :
     9.6      _g1p(g1p), _name(name),
     9.7 -    _all_regions_allocated(0),
     9.8 -    _curr_length(0), _scan_only_prefix(0), _setup_seq_num(0),
     9.9 -    _array_length(0), _surv_rate(NULL), _accum_surv_rate_pred(NULL),
    9.10 -    _accum_surv_rate(0.0), _surv_rate_pred(NULL), _last_pred(0.0),
    9.11      _summary_surv_rates_len(summary_surv_rates_len),
    9.12      _summary_surv_rates_max_len(0),
    9.13 -    _summary_surv_rates(NULL) {
    9.14 -
    9.15 -  // the following will set up the arrays with length 1
    9.16 -  _curr_length = 1;
    9.17 -  stop_adding_regions();
    9.18 -  guarantee( _array_length == 1, "invariant" );
    9.19 -  guarantee( _surv_rate_pred[0] != NULL, "invariant" );
    9.20 -  _surv_rate_pred[0]->add(0.4);
    9.21 -  all_surviving_words_recorded(false);
    9.22 -  _curr_length = 0;
    9.23 -
    9.24 +    _summary_surv_rates(NULL),
    9.25 +    _surv_rate(NULL),
    9.26 +    _accum_surv_rate_pred(NULL),
    9.27 +    _surv_rate_pred(NULL)
    9.28 +{
    9.29 +  reset();
    9.30    if (summary_surv_rates_len > 0) {
    9.31      size_t length = summary_surv_rates_len;
    9.32        _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length);
    9.33 @@ -60,61 +51,80 @@
    9.34    start_adding_regions();
    9.35  }
    9.36  
    9.37 +
    9.38 +void SurvRateGroup::reset()
    9.39 +{
    9.40 +  _all_regions_allocated = 0;
    9.41 +  _scan_only_prefix      = 0;
    9.42 +  _setup_seq_num         = 0;
    9.43 +  _stats_arrays_length   = 0;
    9.44 +  _accum_surv_rate       = 0.0;
    9.45 +  _last_pred             = 0.0;
    9.46 +  // the following will set up the arrays with length 1
    9.47 +  _region_num            = 1;
    9.48 +  stop_adding_regions();
    9.49 +  guarantee( _stats_arrays_length == 1, "invariant" );
    9.50 +  guarantee( _surv_rate_pred[0] != NULL, "invariant" );
    9.51 +  _surv_rate_pred[0]->add(0.4);
    9.52 +  all_surviving_words_recorded(false);
    9.53 +  _region_num = 0;
    9.54 +}
    9.55 +
    9.56 +
    9.57  void
    9.58  SurvRateGroup::start_adding_regions() {
    9.59 -  _setup_seq_num   = _array_length;
    9.60 -  _curr_length     = _scan_only_prefix;
    9.61 +  _setup_seq_num   = _stats_arrays_length;
    9.62 +  _region_num      = _scan_only_prefix;
    9.63    _accum_surv_rate = 0.0;
    9.64  
    9.65  #if 0
    9.66 -  gclog_or_tty->print_cr("start adding regions, seq num %d, length %d",
    9.67 -                         _setup_seq_num, _curr_length);
    9.68 +  gclog_or_tty->print_cr("[%s] start adding regions, seq num %d, length %d",
    9.69 +                         _name, _setup_seq_num, _region_num);
    9.70  #endif // 0
    9.71  }
    9.72  
    9.73  void
    9.74  SurvRateGroup::stop_adding_regions() {
    9.75 -  size_t length = _curr_length;
    9.76  
    9.77  #if 0
    9.78 -  gclog_or_tty->print_cr("stop adding regions, length %d", length);
    9.79 +  gclog_or_tty->print_cr("[%s] stop adding regions, length %d", _name, _region_num);
    9.80  #endif // 0
    9.81  
    9.82 -  if (length > _array_length) {
    9.83 +  if (_region_num > _stats_arrays_length) {
    9.84      double* old_surv_rate = _surv_rate;
    9.85      double* old_accum_surv_rate_pred = _accum_surv_rate_pred;
    9.86      TruncatedSeq** old_surv_rate_pred = _surv_rate_pred;
    9.87  
    9.88 -    _surv_rate = NEW_C_HEAP_ARRAY(double, length);
    9.89 +    _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num);
    9.90      if (_surv_rate == NULL) {
    9.91 -      vm_exit_out_of_memory(sizeof(double) * length,
    9.92 +      vm_exit_out_of_memory(sizeof(double) * _region_num,
    9.93                              "Not enough space for surv rate array.");
    9.94      }
    9.95 -    _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, length);
    9.96 +    _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num);
    9.97      if (_accum_surv_rate_pred == NULL) {
    9.98 -      vm_exit_out_of_memory(sizeof(double) * length,
    9.99 +      vm_exit_out_of_memory(sizeof(double) * _region_num,
   9.100                           "Not enough space for accum surv rate pred array.");
   9.101      }
   9.102 -    _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, length);
   9.103 +    _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num);
   9.104      if (_surv_rate == NULL) {
   9.105 -      vm_exit_out_of_memory(sizeof(TruncatedSeq*) * length,
   9.106 +      vm_exit_out_of_memory(sizeof(TruncatedSeq*) * _region_num,
   9.107                              "Not enough space for surv rate pred array.");
   9.108      }
   9.109  
   9.110 -    for (size_t i = 0; i < _array_length; ++i)
   9.111 +    for (size_t i = 0; i < _stats_arrays_length; ++i)
   9.112        _surv_rate_pred[i] = old_surv_rate_pred[i];
   9.113  
   9.114  #if 0
   9.115 -    gclog_or_tty->print_cr("stop adding regions, new seqs %d to %d",
   9.116 -                  _array_length, length - 1);
   9.117 +    gclog_or_tty->print_cr("[%s] stop adding regions, new seqs %d to %d",
   9.118 +                  _name, _array_length, _region_num - 1);
   9.119  #endif // 0
   9.120  
   9.121 -    for (size_t i = _array_length; i < length; ++i) {
   9.122 +    for (size_t i = _stats_arrays_length; i < _region_num; ++i) {
   9.123        _surv_rate_pred[i] = new TruncatedSeq(10);
   9.124        // _surv_rate_pred[i]->add(last_pred);
   9.125      }
   9.126  
   9.127 -    _array_length = length;
   9.128 +    _stats_arrays_length = _region_num;
   9.129  
   9.130      if (old_surv_rate != NULL)
   9.131        FREE_C_HEAP_ARRAY(double, old_surv_rate);
   9.132 @@ -124,7 +134,7 @@
   9.133        FREE_C_HEAP_ARRAY(NumberSeq*, old_surv_rate_pred);
   9.134    }
   9.135  
   9.136 -  for (size_t i = 0; i < _array_length; ++i)
   9.137 +  for (size_t i = 0; i < _stats_arrays_length; ++i)
   9.138      _surv_rate[i] = 0.0;
   9.139  }
   9.140  
   9.141 @@ -135,7 +145,7 @@
   9.142  
   9.143    double ret = _accum_surv_rate;
   9.144    if (adjustment > 0) {
   9.145 -    TruncatedSeq* seq = get_seq(_curr_length+1);
   9.146 +    TruncatedSeq* seq = get_seq(_region_num+1);
   9.147      double surv_rate = _g1p->get_new_prediction(seq);
   9.148      ret += surv_rate;
   9.149    }
   9.150 @@ -145,23 +155,23 @@
   9.151  
   9.152  int
   9.153  SurvRateGroup::next_age_index() {
   9.154 -  TruncatedSeq* seq = get_seq(_curr_length);
   9.155 +  TruncatedSeq* seq = get_seq(_region_num);
   9.156    double surv_rate = _g1p->get_new_prediction(seq);
   9.157    _accum_surv_rate += surv_rate;
   9.158  
   9.159 -  ++_curr_length;
   9.160 +  ++_region_num;
   9.161    return (int) ++_all_regions_allocated;
   9.162  }
   9.163  
   9.164  void
   9.165  SurvRateGroup::record_scan_only_prefix(size_t scan_only_prefix) {
   9.166 -  guarantee( scan_only_prefix <= _curr_length, "pre-condition" );
   9.167 +  guarantee( scan_only_prefix <= _region_num, "pre-condition" );
   9.168    _scan_only_prefix = scan_only_prefix;
   9.169  }
   9.170  
   9.171  void
   9.172  SurvRateGroup::record_surviving_words(int age_in_group, size_t surv_words) {
   9.173 -  guarantee( 0 <= age_in_group && (size_t) age_in_group < _curr_length,
   9.174 +  guarantee( 0 <= age_in_group && (size_t) age_in_group < _region_num,
   9.175               "pre-condition" );
   9.176    guarantee( _surv_rate[age_in_group] <= 0.00001,
   9.177               "should only update each slot once" );
   9.178 @@ -178,15 +188,15 @@
   9.179  
   9.180  void
   9.181  SurvRateGroup::all_surviving_words_recorded(bool propagate) {
   9.182 -  if (propagate && _curr_length > 0) { // conservative
   9.183 -    double surv_rate = _surv_rate_pred[_curr_length-1]->last();
   9.184 +  if (propagate && _region_num > 0) { // conservative
   9.185 +    double surv_rate = _surv_rate_pred[_region_num-1]->last();
   9.186  
   9.187  #if 0
   9.188      gclog_or_tty->print_cr("propagating %1.2lf from %d to %d",
   9.189                    surv_rate, _curr_length, _array_length - 1);
   9.190  #endif // 0
   9.191  
   9.192 -    for (size_t i = _curr_length; i < _array_length; ++i) {
   9.193 +    for (size_t i = _region_num; i < _stats_arrays_length; ++i) {
   9.194        guarantee( _surv_rate[i] <= 0.00001,
   9.195                   "the slot should not have been updated" );
   9.196        _surv_rate_pred[i]->add(surv_rate);
   9.197 @@ -195,7 +205,7 @@
   9.198  
   9.199    double accum = 0.0;
   9.200    double pred = 0.0;
   9.201 -  for (size_t i = 0; i < _array_length; ++i) {
   9.202 +  for (size_t i = 0; i < _stats_arrays_length; ++i) {
   9.203      pred = _g1p->get_new_prediction(_surv_rate_pred[i]);
   9.204      if (pred > 1.0) pred = 1.0;
   9.205      accum += pred;
   9.206 @@ -209,8 +219,8 @@
   9.207  void
   9.208  SurvRateGroup::print() {
   9.209    gclog_or_tty->print_cr("Surv Rate Group: %s (%d entries, %d scan-only)",
   9.210 -                _name, _curr_length, _scan_only_prefix);
   9.211 -  for (size_t i = 0; i < _curr_length; ++i) {
   9.212 +                _name, _region_num, _scan_only_prefix);
   9.213 +  for (size_t i = 0; i < _region_num; ++i) {
   9.214      gclog_or_tty->print_cr("    age %4d   surv rate %6.2lf %%   pred %6.2lf %%%s",
   9.215                    i, _surv_rate[i] * 100.0,
   9.216                    _g1p->get_new_prediction(_surv_rate_pred[i]) * 100.0,
    10.1 --- a/src/share/vm/gc_implementation/g1/survRateGroup.hpp	Thu Feb 05 11:42:10 2009 -0800
    10.2 +++ b/src/share/vm/gc_implementation/g1/survRateGroup.hpp	Fri Feb 06 01:38:50 2009 +0300
    10.3 @@ -29,7 +29,7 @@
    10.4    G1CollectorPolicy* _g1p;
    10.5    const char* _name;
    10.6  
    10.7 -  size_t  _array_length;
    10.8 +  size_t  _stats_arrays_length;
    10.9    double* _surv_rate;
   10.10    double* _accum_surv_rate_pred;
   10.11    double  _last_pred;
   10.12 @@ -40,7 +40,7 @@
   10.13    size_t         _summary_surv_rates_max_len;
   10.14  
   10.15    int _all_regions_allocated;
   10.16 -  size_t _curr_length;
   10.17 +  size_t _region_num;
   10.18    size_t _scan_only_prefix;
   10.19    size_t _setup_seq_num;
   10.20  
   10.21 @@ -48,6 +48,7 @@
   10.22    SurvRateGroup(G1CollectorPolicy* g1p,
   10.23                  const char* name,
   10.24                  size_t summary_surv_rates_len);
   10.25 +  void reset();
   10.26    void start_adding_regions();
   10.27    void stop_adding_regions();
   10.28    void record_scan_only_prefix(size_t scan_only_prefix);
   10.29 @@ -55,22 +56,21 @@
   10.30    void all_surviving_words_recorded(bool propagate);
   10.31    const char* name() { return _name; }
   10.32  
   10.33 -  size_t region_num() { return _curr_length; }
   10.34 +  size_t region_num() { return _region_num; }
   10.35    size_t scan_only_length() { return _scan_only_prefix; }
   10.36    double accum_surv_rate_pred(int age) {
   10.37      assert(age >= 0, "must be");
   10.38 -    if ((size_t)age < _array_length)
   10.39 +    if ((size_t)age < _stats_arrays_length)
   10.40        return _accum_surv_rate_pred[age];
   10.41      else {
   10.42 -      double diff = (double) (age - _array_length + 1);
   10.43 -      return _accum_surv_rate_pred[_array_length-1] + diff * _last_pred;
   10.44 +      double diff = (double) (age - _stats_arrays_length + 1);
   10.45 +      return _accum_surv_rate_pred[_stats_arrays_length-1] + diff * _last_pred;
   10.46      }
   10.47    }
   10.48  
   10.49    double accum_surv_rate(size_t adjustment);
   10.50  
   10.51    TruncatedSeq* get_seq(size_t age) {
   10.52 -    guarantee( 0 <= age, "pre-condition" );
   10.53      if (age >= _setup_seq_num) {
   10.54        guarantee( _setup_seq_num > 0, "invariant" );
   10.55        age = _setup_seq_num-1;
    11.1 --- a/src/share/vm/gc_implementation/includeDB_gc_g1	Thu Feb 05 11:42:10 2009 -0800
    11.2 +++ b/src/share/vm/gc_implementation/includeDB_gc_g1	Fri Feb 06 01:38:50 2009 +0300
    11.3 @@ -172,6 +172,7 @@
    11.4  g1CollectorPolicy.cpp                   g1CollectorPolicy.hpp
    11.5  g1CollectorPolicy.cpp                   heapRegionRemSet.hpp
    11.6  g1CollectorPolicy.cpp			mutexLocker.hpp
    11.7 +g1CollectorPolicy.cpp			gcPolicyCounters.hpp
    11.8  
    11.9  g1CollectorPolicy.hpp                   collectorPolicy.hpp
   11.10  g1CollectorPolicy.hpp                   collectionSetChooser.hpp
   11.11 @@ -272,6 +273,7 @@
   11.12  heapRegion.hpp                          watermark.hpp
   11.13  heapRegion.hpp				g1_specialized_oop_closures.hpp
   11.14  heapRegion.hpp				survRateGroup.hpp
   11.15 +heapRegion.hpp				ageTable.hpp
   11.16  
   11.17  heapRegionRemSet.hpp			sparsePRT.hpp
   11.18  
    12.1 --- a/src/share/vm/gc_implementation/shared/ageTable.cpp	Thu Feb 05 11:42:10 2009 -0800
    12.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.cpp	Fri Feb 06 01:38:50 2009 +0300
    12.3 @@ -67,6 +67,12 @@
    12.4    }
    12.5  }
    12.6  
    12.7 +void ageTable::merge_par(ageTable* subTable) {
    12.8 +  for (int i = 0; i < table_size; i++) {
    12.9 +    Atomic::add_ptr(subTable->sizes[i], &sizes[i]);
   12.10 +  }
   12.11 +}
   12.12 +
   12.13  int ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
   12.14    size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
   12.15    size_t total = 0;
    13.1 --- a/src/share/vm/gc_implementation/shared/ageTable.hpp	Thu Feb 05 11:42:10 2009 -0800
    13.2 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp	Fri Feb 06 01:38:50 2009 +0300
    13.3 @@ -56,6 +56,7 @@
    13.4    // Merge another age table with the current one.  Used
    13.5    // for parallel young generation gc.
    13.6    void merge(ageTable* subTable);
    13.7 +  void merge_par(ageTable* subTable);
    13.8  
    13.9    // calculate new tenuring threshold based on age information
   13.10    int compute_tenuring_threshold(size_t survivor_capacity);

mercurial