generation.cpp revision 8413:92457dfb91bd
1/*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "gc/serial/genMarkSweep.hpp"
27#include "gc/shared/blockOffsetTable.inline.hpp"
28#include "gc/shared/cardTableRS.hpp"
29#include "gc/shared/collectedHeap.inline.hpp"
30#include "gc/shared/gcLocker.inline.hpp"
31#include "gc/shared/gcTimer.hpp"
32#include "gc/shared/gcTrace.hpp"
33#include "gc/shared/genCollectedHeap.hpp"
34#include "gc/shared/genOopClosures.hpp"
35#include "gc/shared/genOopClosures.inline.hpp"
36#include "gc/shared/generation.hpp"
37#include "gc/shared/space.inline.hpp"
38#include "gc/shared/spaceDecorator.hpp"
39#include "memory/allocation.inline.hpp"
40#include "oops/oop.inline.hpp"
41#include "runtime/java.hpp"
42#include "utilities/copy.hpp"
43#include "utilities/events.hpp"
44
45Generation::Generation(ReservedSpace rs, size_t initial_size, int level) :
46  _level(level),
47  _ref_processor(NULL) {
48  if (!_virtual_space.initialize(rs, initial_size)) {
49    vm_exit_during_initialization("Could not reserve enough space for "
50                    "object heap");
51  }
52  // Mangle all of the the initial generation.
53  if (ZapUnusedHeapArea) {
54    MemRegion mangle_region((HeapWord*)_virtual_space.low(),
55      (HeapWord*)_virtual_space.high());
56    SpaceMangler::mangle_region(mangle_region);
57  }
58  _reserved = MemRegion((HeapWord*)_virtual_space.low_boundary(),
59          (HeapWord*)_virtual_space.high_boundary());
60}
61
62GenerationSpec* Generation::spec() {
63  GenCollectedHeap* gch = GenCollectedHeap::heap();
64  assert(level() == 0 || level() == 1, "Bad gen level");
65  return level() == 0 ? gch->gen_policy()->young_gen_spec() : gch->gen_policy()->old_gen_spec();
66}
67
68size_t Generation::max_capacity() const {
69  return reserved().byte_size();
70}
71
72void Generation::print_heap_change(size_t prev_used) const {
73  if (PrintGCDetails && Verbose) {
74    gclog_or_tty->print(" "  SIZE_FORMAT
75                        "->" SIZE_FORMAT
76                        "("  SIZE_FORMAT ")",
77                        prev_used, used(), capacity());
78  } else {
79    gclog_or_tty->print(" "  SIZE_FORMAT "K"
80                        "->" SIZE_FORMAT "K"
81                        "("  SIZE_FORMAT "K)",
82                        prev_used / K, used() / K, capacity() / K);
83  }
84}
85
86// By default we get a single threaded default reference processor;
87// generations needing multi-threaded refs processing or discovery override this method.
88void Generation::ref_processor_init() {
89  assert(_ref_processor == NULL, "a reference processor already exists");
90  assert(!_reserved.is_empty(), "empty generation?");
91  _ref_processor = new ReferenceProcessor(_reserved);    // a vanilla reference processor
92  if (_ref_processor == NULL) {
93    vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
94  }
95}
96
97void Generation::print() const { print_on(tty); }
98
99void Generation::print_on(outputStream* st)  const {
100  st->print(" %-20s", name());
101  st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
102             capacity()/K, used()/K);
103  st->print_cr(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")",
104              p2i(_virtual_space.low_boundary()),
105              p2i(_virtual_space.high()),
106              p2i(_virtual_space.high_boundary()));
107}
108
109void Generation::print_summary_info() { print_summary_info_on(tty); }
110
111void Generation::print_summary_info_on(outputStream* st) {
112  StatRecord* sr = stat_record();
113  double time = sr->accumulated_time.seconds();
114  st->print_cr("[Accumulated GC generation %d time %3.7f secs, "
115               "%d GC's, avg GC time %3.7f]",
116               level(), time, sr->invocations,
117               sr->invocations > 0 ? time / sr->invocations : 0.0);
118}
119
120// Utility iterator classes
121
122class GenerationIsInReservedClosure : public SpaceClosure {
123 public:
124  const void* _p;
125  Space* sp;
126  virtual void do_space(Space* s) {
127    if (sp == NULL) {
128      if (s->is_in_reserved(_p)) sp = s;
129    }
130  }
131  GenerationIsInReservedClosure(const void* p) : _p(p), sp(NULL) {}
132};
133
134class GenerationIsInClosure : public SpaceClosure {
135 public:
136  const void* _p;
137  Space* sp;
138  virtual void do_space(Space* s) {
139    if (sp == NULL) {
140      if (s->is_in(_p)) sp = s;
141    }
142  }
143  GenerationIsInClosure(const void* p) : _p(p), sp(NULL) {}
144};
145
146bool Generation::is_in(const void* p) const {
147  GenerationIsInClosure blk(p);
148  ((Generation*)this)->space_iterate(&blk);
149  return blk.sp != NULL;
150}
151
152Generation* Generation::next_gen() const {
153  GenCollectedHeap* gch = GenCollectedHeap::heap();
154  if (level() == 0) {
155    return gch->old_gen();
156  } else {
157    return NULL;
158  }
159}
160
161size_t Generation::max_contiguous_available() const {
162  // The largest number of contiguous free words in this or any higher generation.
163  size_t max = 0;
164  for (const Generation* gen = this; gen != NULL; gen = gen->next_gen()) {
165    size_t avail = gen->contiguous_available();
166    if (avail > max) {
167      max = avail;
168    }
169  }
170  return max;
171}
172
173bool Generation::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
174  size_t available = max_contiguous_available();
175  bool   res = (available >= max_promotion_in_bytes);
176  if (PrintGC && Verbose) {
177    gclog_or_tty->print_cr(
178      "Generation: promo attempt is%s safe: available("SIZE_FORMAT") %s max_promo("SIZE_FORMAT")",
179      res? "":" not", available, res? ">=":"<",
180      max_promotion_in_bytes);
181  }
182  return res;
183}
184
185// Ignores "ref" and calls allocate().
186oop Generation::promote(oop obj, size_t obj_size) {
187  assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
188
189#ifndef PRODUCT
190  if (GenCollectedHeap::heap()->promotion_should_fail()) {
191    return NULL;
192  }
193#endif  // #ifndef PRODUCT
194
195  HeapWord* result = allocate(obj_size, false);
196  if (result != NULL) {
197    Copy::aligned_disjoint_words((HeapWord*)obj, result, obj_size);
198    return oop(result);
199  } else {
200    GenCollectedHeap* gch = GenCollectedHeap::heap();
201    return gch->handle_failed_promotion(this, obj, obj_size);
202  }
203}
204
205oop Generation::par_promote(int thread_num,
206                            oop obj, markOop m, size_t word_sz) {
207  // Could do a bad general impl here that gets a lock.  But no.
208  ShouldNotCallThis();
209  return NULL;
210}
211
212Space* Generation::space_containing(const void* p) const {
213  GenerationIsInReservedClosure blk(p);
214  // Cast away const
215  ((Generation*)this)->space_iterate(&blk);
216  return blk.sp;
217}
218
219// Some of these are mediocre general implementations.  Should be
220// overridden to get better performance.
221
222class GenerationBlockStartClosure : public SpaceClosure {
223 public:
224  const void* _p;
225  HeapWord* _start;
226  virtual void do_space(Space* s) {
227    if (_start == NULL && s->is_in_reserved(_p)) {
228      _start = s->block_start(_p);
229    }
230  }
231  GenerationBlockStartClosure(const void* p) { _p = p; _start = NULL; }
232};
233
234HeapWord* Generation::block_start(const void* p) const {
235  GenerationBlockStartClosure blk(p);
236  // Cast away const
237  ((Generation*)this)->space_iterate(&blk);
238  return blk._start;
239}
240
241class GenerationBlockSizeClosure : public SpaceClosure {
242 public:
243  const HeapWord* _p;
244  size_t size;
245  virtual void do_space(Space* s) {
246    if (size == 0 && s->is_in_reserved(_p)) {
247      size = s->block_size(_p);
248    }
249  }
250  GenerationBlockSizeClosure(const HeapWord* p) { _p = p; size = 0; }
251};
252
253size_t Generation::block_size(const HeapWord* p) const {
254  GenerationBlockSizeClosure blk(p);
255  // Cast away const
256  ((Generation*)this)->space_iterate(&blk);
257  assert(blk.size > 0, "seems reasonable");
258  return blk.size;
259}
260
261class GenerationBlockIsObjClosure : public SpaceClosure {
262 public:
263  const HeapWord* _p;
264  bool is_obj;
265  virtual void do_space(Space* s) {
266    if (!is_obj && s->is_in_reserved(_p)) {
267      is_obj |= s->block_is_obj(_p);
268    }
269  }
270  GenerationBlockIsObjClosure(const HeapWord* p) { _p = p; is_obj = false; }
271};
272
273bool Generation::block_is_obj(const HeapWord* p) const {
274  GenerationBlockIsObjClosure blk(p);
275  // Cast away const
276  ((Generation*)this)->space_iterate(&blk);
277  return blk.is_obj;
278}
279
280class GenerationOopIterateClosure : public SpaceClosure {
281 public:
282  ExtendedOopClosure* _cl;
283  virtual void do_space(Space* s) {
284    s->oop_iterate(_cl);
285  }
286  GenerationOopIterateClosure(ExtendedOopClosure* cl) :
287    _cl(cl) {}
288};
289
290void Generation::oop_iterate(ExtendedOopClosure* cl) {
291  GenerationOopIterateClosure blk(cl);
292  space_iterate(&blk);
293}
294
295void Generation::younger_refs_in_space_iterate(Space* sp,
296                                               OopsInGenClosure* cl) {
297  GenRemSet* rs = GenCollectedHeap::heap()->rem_set();
298  rs->younger_refs_in_space_iterate(sp, cl);
299}
300
301class GenerationObjIterateClosure : public SpaceClosure {
302 private:
303  ObjectClosure* _cl;
304 public:
305  virtual void do_space(Space* s) {
306    s->object_iterate(_cl);
307  }
308  GenerationObjIterateClosure(ObjectClosure* cl) : _cl(cl) {}
309};
310
311void Generation::object_iterate(ObjectClosure* cl) {
312  GenerationObjIterateClosure blk(cl);
313  space_iterate(&blk);
314}
315
316class GenerationSafeObjIterateClosure : public SpaceClosure {
317 private:
318  ObjectClosure* _cl;
319 public:
320  virtual void do_space(Space* s) {
321    s->safe_object_iterate(_cl);
322  }
323  GenerationSafeObjIterateClosure(ObjectClosure* cl) : _cl(cl) {}
324};
325
326void Generation::safe_object_iterate(ObjectClosure* cl) {
327  GenerationSafeObjIterateClosure blk(cl);
328  space_iterate(&blk);
329}
330
331void Generation::prepare_for_compaction(CompactPoint* cp) {
332  // Generic implementation, can be specialized
333  CompactibleSpace* space = first_compaction_space();
334  while (space != NULL) {
335    space->prepare_for_compaction(cp);
336    space = space->next_compaction_space();
337  }
338}
339
340class AdjustPointersClosure: public SpaceClosure {
341 public:
342  void do_space(Space* sp) {
343    sp->adjust_pointers();
344  }
345};
346
347void Generation::adjust_pointers() {
348  // Note that this is done over all spaces, not just the compactible
349  // ones.
350  AdjustPointersClosure blk;
351  space_iterate(&blk, true);
352}
353
354void Generation::compact() {
355  CompactibleSpace* sp = first_compaction_space();
356  while (sp != NULL) {
357    sp->compact();
358    sp = sp->next_compaction_space();
359  }
360}
361