parNewGeneration.hpp 15.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP
#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP

S
sla 已提交
28
#include "gc_implementation/shared/gcTrace.hpp"
29
#include "gc_implementation/shared/parGCAllocBuffer.hpp"
S
sla 已提交
30
#include "gc_implementation/shared/copyFailedInfo.hpp"
31
#include "memory/defNewGeneration.hpp"
32
#include "memory/padded.hpp"
33 34
#include "utilities/taskqueue.hpp"

D
duke 已提交
35 36 37 38 39 40 41 42 43 44 45
class ChunkArray;
class ParScanWithoutBarrierClosure;
class ParScanWithBarrierClosure;
class ParRootScanWithoutBarrierClosure;
class ParRootScanWithBarrierTwoGensClosure;
class ParEvacuateFollowersClosure;

// It would be better if these types could be kept local to the .cpp file,
// but they must be here to allow ParScanClosure::do_oop_work to be defined
// in genOopClosures.inline.hpp.

J
jcoomes 已提交
46
typedef Padded<OopTaskQueue> ObjToScanQueue;
Z
zgu 已提交
47
typedef GenericTaskQueueSet<ObjToScanQueue, mtGC> ObjToScanQueueSet;
D
duke 已提交
48 49

class ParKeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
50
 private:
D
duke 已提交
51
  ParScanWeakRefClosure* _par_cl;
52 53
 protected:
  template <class T> void do_oop_work(T* p);
D
duke 已提交
54 55
 public:
  ParKeepAliveClosure(ParScanWeakRefClosure* cl);
56 57
  virtual void do_oop(oop* p);
  virtual void do_oop(narrowOop* p);
D
duke 已提交
58 59 60 61 62
};

// The state needed by thread performing parallel young-gen collection.
class ParScanThreadState {
  friend class ParScanThreadStateSet;
63
 private:
D
duke 已提交
64
  ObjToScanQueue *_work_queue;
Z
zgu 已提交
65
  Stack<oop, mtGC>* const _overflow_stack;
D
duke 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

  ParGCAllocBuffer _to_space_alloc_buffer;

  ParScanWithoutBarrierClosure         _to_space_closure; // scan_without_gc_barrier
  ParScanWithBarrierClosure            _old_gen_closure; // scan_with_gc_barrier
  ParRootScanWithoutBarrierClosure     _to_space_root_closure; // scan_root_without_gc_barrier
  // One of these two will be passed to process_strong_roots, which will
  // set its generation.  The first is for two-gen configs where the
  // old gen collects the perm gen; the second is for arbitrary configs.
  // The second isn't used right now (it used to be used for the train, an
  // incremental collector) but the declaration has been left as a reminder.
  ParRootScanWithBarrierTwoGensClosure _older_gen_closure;
  // This closure will always be bound to the old gen; it will be used
  // in evacuate_followers.
  ParRootScanWithBarrierTwoGensClosure _old_gen_root_closure; // scan_old_root_with_gc_barrier
  ParEvacuateFollowersClosure          _evacuate_followers;
  DefNewGeneration::IsAliveClosure     _is_alive_closure;
  ParScanWeakRefClosure                _scan_weak_ref_closure;
  ParKeepAliveClosure                  _keep_alive_closure;


  Space* _to_space;
  Space* to_space() { return _to_space; }

90 91 92
  ParNewGeneration* _young_gen;
  ParNewGeneration* young_gen() const { return _young_gen; }

D
duke 已提交
93 94 95 96 97 98 99 100 101 102 103
  Generation* _old_gen;
  Generation* old_gen() { return _old_gen; }

  HeapWord *_young_old_boundary;

  int _hash_seed;
  int _thread_num;
  ageTable _ageTable;

  bool _to_space_full;

104 105 106 107 108
#if TASKQUEUE_STATS
  size_t _term_attempts;
  size_t _overflow_refills;
  size_t _overflow_refill_objs;
#endif // TASKQUEUE_STATS
D
duke 已提交
109

110
  // Stats for promotion failure
S
sla 已提交
111
  PromotionFailedInfo _promotion_failed_info;
112

D
duke 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
  // Timing numbers.
  double _start;
  double _start_strong_roots;
  double _strong_roots_time;
  double _start_term;
  double _term_time;

  // Helper for trim_queues. Scans subset of an array and makes
  // remainder available for work stealing.
  void scan_partial_array_and_push_remainder(oop obj);

  // In support of CMS' parallel rescan of survivor space.
  ChunkArray* _survivor_chunk_array;
  ChunkArray* survivor_chunk_array() { return _survivor_chunk_array; }

  void record_survivor_plab(HeapWord* plab_start, size_t plab_word_size);

  ParScanThreadState(Space* to_space_, ParNewGeneration* gen_,
                     Generation* old_gen_, int thread_num_,
132
                     ObjToScanQueueSet* work_queue_set_,
Z
zgu 已提交
133
                     Stack<oop, mtGC>* overflow_stacks_,
134
                     size_t desired_plab_sz_,
D
duke 已提交
135 136
                     ParallelTaskTerminator& term_);

137
 public:
D
duke 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
  ageTable* age_table() {return &_ageTable;}

  ObjToScanQueue* work_queue() { return _work_queue; }

  ParGCAllocBuffer* to_space_alloc_buffer() {
    return &_to_space_alloc_buffer;
  }

  ParEvacuateFollowersClosure&      evacuate_followers_closure() { return _evacuate_followers; }
  DefNewGeneration::IsAliveClosure& is_alive_closure() { return _is_alive_closure; }
  ParScanWeakRefClosure&            scan_weak_ref_closure() { return _scan_weak_ref_closure; }
  ParKeepAliveClosure&              keep_alive_closure() { return _keep_alive_closure; }
  ParScanClosure&                   older_gen_closure() { return _older_gen_closure; }
  ParRootScanWithoutBarrierClosure& to_space_root_closure() { return _to_space_root_closure; };

  // Decrease queue size below "max_size".
  void trim_queues(int max_size);

156
  // Private overflow stack usage
Z
zgu 已提交
157
  Stack<oop, mtGC>* overflow_stack() { return _overflow_stack; }
158 159 160
  bool take_from_overflow_stack();
  void push_on_overflow_stack(oop p);

D
duke 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
  // Is new_obj a candidate for scan_partial_array_and_push_remainder method.
  inline bool should_be_partially_scanned(oop new_obj, oop old_obj) const;

  int* hash_seed()  { return &_hash_seed; }
  int  thread_num() { return _thread_num; }

  // Allocate a to-space block of size "sz", or else return NULL.
  HeapWord* alloc_in_to_space_slow(size_t word_sz);

  HeapWord* alloc_in_to_space(size_t word_sz) {
    HeapWord* obj = to_space_alloc_buffer()->allocate(word_sz);
    if (obj != NULL) return obj;
    else return alloc_in_to_space_slow(word_sz);
  }

  HeapWord* young_old_boundary() { return _young_old_boundary; }

  void set_young_old_boundary(HeapWord *boundary) {
    _young_old_boundary = boundary;
  }

  // Undo the most recent allocation ("obj", of "word_sz").
  void undo_alloc_in_to_space(HeapWord* obj, size_t word_sz);

185
  // Promotion failure stats
S
sla 已提交
186 187
  void register_promotion_failure(size_t sz) {
    _promotion_failed_info.register_copy_failure(sz);
188
  }
S
sla 已提交
189 190 191 192 193 194 195
  PromotionFailedInfo& promotion_failed_info() {
    return _promotion_failed_info;
  }
  bool promotion_failed() {
    return _promotion_failed_info.has_failed();
  }
  void print_promotion_failure_size();
196

197 198 199 200 201 202 203 204 205 206
#if TASKQUEUE_STATS
  TaskQueueStats & taskqueue_stats() const { return _work_queue->stats; }

  size_t term_attempts() const             { return _term_attempts; }
  size_t overflow_refills() const          { return _overflow_refills; }
  size_t overflow_refill_objs() const      { return _overflow_refill_objs; }

  void note_term_attempt()                 { ++_term_attempts; }
  void note_overflow_refill(size_t objs)   {
    ++_overflow_refills; _overflow_refill_objs += objs;
D
duke 已提交
207 208
  }

209 210 211
  void reset_stats();
#endif // TASKQUEUE_STATS

D
duke 已提交
212 213 214 215 216 217
  void start_strong_roots() {
    _start_strong_roots = os::elapsedTime();
  }
  void end_strong_roots() {
    _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
  }
218
  double strong_roots_time() const { return _strong_roots_time; }
D
duke 已提交
219
  void start_term_time() {
220
    TASKQUEUE_STATS_ONLY(note_term_attempt());
D
duke 已提交
221 222 223 224 225
    _start_term = os::elapsedTime();
  }
  void end_term_time() {
    _term_time += (os::elapsedTime() - _start_term);
  }
226
  double term_time() const { return _term_time; }
D
duke 已提交
227

228
  double elapsed_time() const {
D
duke 已提交
229 230 231 232 233
    return os::elapsedTime() - _start;
  }
};

class ParNewGenTask: public AbstractGangTask {
234 235 236 237
 private:
  ParNewGeneration*            _gen;
  Generation*                  _next_gen;
  HeapWord*                    _young_old_boundary;
D
duke 已提交
238 239 240 241 242 243 244 245 246 247
  class ParScanThreadStateSet* _state_set;

public:
  ParNewGenTask(ParNewGeneration*      gen,
                Generation*            next_gen,
                HeapWord*              young_old_boundary,
                ParScanThreadStateSet* state_set);

  HeapWord* young_old_boundary() { return _young_old_boundary; }

248
  void work(uint worker_id);
249 250 251 252

  // Reset the terminator in ParScanThreadStateSet for
  // "active_workers" threads.
  virtual void set_for_termination(int active_workers);
D
duke 已提交
253 254 255
};

class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
256 257
 protected:
  template <class T> void do_oop_work(T* p);
D
duke 已提交
258 259
 public:
  KeepAliveClosure(ScanWeakRefClosure* cl);
260 261
  virtual void do_oop(oop* p);
  virtual void do_oop(narrowOop* p);
D
duke 已提交
262 263 264
};

class EvacuateFollowersClosureGeneral: public VoidClosure {
265 266 267 268 269 270 271 272 273 274
 private:
  GenCollectedHeap* _gch;
  int               _level;
  OopsInGenClosure* _scan_cur_or_nonheap;
  OopsInGenClosure* _scan_older;
 public:
  EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level,
                                  OopsInGenClosure* cur,
                                  OopsInGenClosure* older);
  virtual void do_void();
D
duke 已提交
275 276 277 278 279
};

// Closure for scanning ParNewGeneration.
// Same as ScanClosure, except does parallel GC barrier.
class ScanClosureWithParBarrier: public ScanClosure {
280 281 282
 protected:
  template <class T> void do_oop_work(T* p);
 public:
D
duke 已提交
283
  ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier);
284 285
  virtual void do_oop(oop* p);
  virtual void do_oop(narrowOop* p);
D
duke 已提交
286 287 288 289
};

// Implements AbstractRefProcTaskExecutor for ParNew.
class ParNewRefProcTaskExecutor: public AbstractRefProcTaskExecutor {
290 291 292 293
 private:
  ParNewGeneration&      _generation;
  ParScanThreadStateSet& _state_set;
 public:
D
duke 已提交
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
  ParNewRefProcTaskExecutor(ParNewGeneration& generation,
                            ParScanThreadStateSet& state_set)
    : _generation(generation), _state_set(state_set)
  { }

  // Executes a task using worker threads.
  virtual void execute(ProcessTask& task);
  virtual void execute(EnqueueTask& task);
  // Switch to single threaded mode.
  virtual void set_single_threaded_mode();
};


// A Generation that does parallel young-gen collection.

class ParNewGeneration: public DefNewGeneration {
  friend class ParNewGenTask;
  friend class ParNewRefProcTask;
  friend class ParNewRefProcTaskExecutor;
  friend class ParScanThreadStateSet;
314
  friend class ParEvacuateFollowersClosure;
D
duke 已提交
315

316
 private:
317
  // The per-worker-thread work queues
D
duke 已提交
318 319
  ObjToScanQueueSet* _task_queues;

320
  // Per-worker-thread local overflow stacks
Z
zgu 已提交
321
  Stack<oop, mtGC>* _overflow_stacks;
322

D
duke 已提交
323 324 325 326 327 328 329
  // Desired size of survivor space plab's
  PLABStats _plab_stats;

  // A list of from-space images of to-be-scanned objects, threaded through
  // klass-pointers (klass information already copied to the forwarded
  // image.)  Manipulated with CAS.
  oop _overflow_list;
330
  NOT_PRODUCT(ssize_t _num_par_pushes;)
D
duke 已提交
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345

  // If true, older generation does not support promotion undo, so avoid.
  static bool _avoid_promotion_undo;

  // This closure is used by the reference processor to filter out
  // references to live referent.
  DefNewGeneration::IsAliveClosure _is_alive_closure;

  static oop real_forwardee_slow(oop obj);
  static void waste_some_time();

  // Preserve the mark of "obj", if necessary, in preparation for its mark
  // word being overwritten with a self-forwarding-pointer.
  void preserve_mark_if_necessary(oop obj, markOop m);

S
sla 已提交
346 347
  void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer);

D
duke 已提交
348 349 350 351 352 353 354 355 356 357
 protected:

  bool _survivor_overflow;

  bool avoid_promotion_undo() { return _avoid_promotion_undo; }
  void set_avoid_promotion_undo(bool v) { _avoid_promotion_undo = v; }

  bool survivor_overflow() { return _survivor_overflow; }
  void set_survivor_overflow(bool v) { _survivor_overflow = v; }

358
 public:
D
duke 已提交
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
  ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level);

  ~ParNewGeneration() {
    for (uint i = 0; i < ParallelGCThreads; i++)
        delete _task_queues->queue(i);

    delete _task_queues;
  }

  virtual void ref_processor_init();
  virtual Generation::Name kind()        { return Generation::ParNew; }
  virtual const char* name() const;
  virtual const char* short_name() const { return "ParNew"; }

  // override
  virtual bool refs_discovery_is_mt()     const {
    assert(UseParNewGC, "ParNewGeneration only when UseParNewGC");
    return ParallelGCThreads > 1;
  }

  // Make the collection virtual.
  virtual void collect(bool   full,
                       bool   clear_all_soft_refs,
                       size_t size,
                       bool   is_tlab);

  // This needs to be visible to the closure function.
  // "obj" is the object to be copied, "m" is a recent value of its mark
  // that must not contain a forwarding pointer (though one might be
  // inserted in "obj"s mark word by a parallel thread).
  inline oop copy_to_survivor_space(ParScanThreadState* par_scan_state,
                             oop obj, size_t obj_sz, markOop m) {
    if (_avoid_promotion_undo) {
       return copy_to_survivor_space_avoiding_promotion_undo(par_scan_state,
                                                             obj, obj_sz, m);
    }

    return copy_to_survivor_space_with_undo(par_scan_state, obj, obj_sz, m);
  }

  oop copy_to_survivor_space_avoiding_promotion_undo(ParScanThreadState* par_scan_state,
                             oop obj, size_t obj_sz, markOop m);

  oop copy_to_survivor_space_with_undo(ParScanThreadState* par_scan_state,
                             oop obj, size_t obj_sz, markOop m);

405 406 407 408
  // in support of testing overflow code
  NOT_PRODUCT(int _overflow_counter;)
  NOT_PRODUCT(bool should_simulate_overflow();)

409 410 411
  // Accessor for overflow list
  oop overflow_list() { return _overflow_list; }

D
duke 已提交
412
  // Push the given (from-space) object on the global overflow list.
413
  void push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state);
D
duke 已提交
414 415

  // If the global overflow list is non-empty, move some tasks from it
416 417
  // onto "work_q" (which need not be empty).  No more than 1/4 of the
  // available space on "work_q" is used.
D
duke 已提交
418
  bool take_from_overflow_list(ParScanThreadState* par_scan_state);
419
  bool take_from_overflow_list_work(ParScanThreadState* par_scan_state);
D
duke 已提交
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437

  // The task queues to be used by parallel GC threads.
  ObjToScanQueueSet* task_queues() {
    return _task_queues;
  }

  PLABStats* plab_stats() {
    return &_plab_stats;
  }

  size_t desired_plab_sz() {
    return _plab_stats.desired_plab_sz();
  }

  static oop real_forwardee(oop obj);

  DEBUG_ONLY(static bool is_legal_forward_ptr(oop p);)
};
438 439

#endif // SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARNEWGENERATION_HPP