comparison agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 //
26 // The ObjectHeap is an abstraction over all generations in the VM
27 // It gives access to all present objects and classes.
28 //
29
30 package sun.jvm.hotspot.oops;
31
32 import java.util.*;
33
34 import sun.jvm.hotspot.debugger.*;
35 import sun.jvm.hotspot.gc_interface.*;
36 import sun.jvm.hotspot.gc_implementation.parallelScavenge.*;
37 import sun.jvm.hotspot.memory.*;
38 import sun.jvm.hotspot.runtime.*;
39 import sun.jvm.hotspot.types.*;
40 import sun.jvm.hotspot.utilities.*;
41
42 public class ObjectHeap {
43
44 private OopHandle symbolKlassHandle;
45 private OopHandle methodKlassHandle;
46 private OopHandle constMethodKlassHandle;
47 private OopHandle methodDataKlassHandle;
48 private OopHandle constantPoolKlassHandle;
49 private OopHandle constantPoolCacheKlassHandle;
50 private OopHandle klassKlassHandle;
51 private OopHandle instanceKlassKlassHandle;
52 private OopHandle typeArrayKlassKlassHandle;
53 private OopHandle objArrayKlassKlassHandle;
54 private OopHandle boolArrayKlassHandle;
55 private OopHandle byteArrayKlassHandle;
56 private OopHandle charArrayKlassHandle;
57 private OopHandle intArrayKlassHandle;
58 private OopHandle shortArrayKlassHandle;
59 private OopHandle longArrayKlassHandle;
60 private OopHandle singleArrayKlassHandle;
61 private OopHandle doubleArrayKlassHandle;
62 private OopHandle arrayKlassKlassHandle;
63 private OopHandle compiledICHolderKlassHandle;
64
65 private SymbolKlass symbolKlassObj;
66 private MethodKlass methodKlassObj;
67 private ConstMethodKlass constMethodKlassObj;
68 private MethodDataKlass methodDataKlassObj;
69 private ConstantPoolKlass constantPoolKlassObj;
70 private ConstantPoolCacheKlass constantPoolCacheKlassObj;
71 private KlassKlass klassKlassObj;
72 private InstanceKlassKlass instanceKlassKlassObj;
73 private TypeArrayKlassKlass typeArrayKlassKlassObj;
74 private ObjArrayKlassKlass objArrayKlassKlassObj;
75 private TypeArrayKlass boolArrayKlassObj;
76 private TypeArrayKlass byteArrayKlassObj;
77 private TypeArrayKlass charArrayKlassObj;
78 private TypeArrayKlass intArrayKlassObj;
79 private TypeArrayKlass shortArrayKlassObj;
80 private TypeArrayKlass longArrayKlassObj;
81 private TypeArrayKlass singleArrayKlassObj;
82 private TypeArrayKlass doubleArrayKlassObj;
83 private ArrayKlassKlass arrayKlassKlassObj;
84 private CompiledICHolderKlass compiledICHolderKlassObj;
85
86 public void initialize(TypeDataBase db) throws WrongTypeException {
87 // Lookup the roots in the object hierarchy.
88 Type universeType = db.lookupType("Universe");
89
90 symbolKlassHandle = universeType.getOopField("_symbolKlassObj").getValue();
91 symbolKlassObj = new SymbolKlass(symbolKlassHandle, this);
92
93 methodKlassHandle = universeType.getOopField("_methodKlassObj").getValue();
94 methodKlassObj = new MethodKlass(methodKlassHandle, this);
95
96 constMethodKlassHandle = universeType.getOopField("_constMethodKlassObj").getValue();
97 constMethodKlassObj = new ConstMethodKlass(constMethodKlassHandle, this);
98
99 constantPoolKlassHandle = universeType.getOopField("_constantPoolKlassObj").getValue();
100 constantPoolKlassObj = new ConstantPoolKlass(constantPoolKlassHandle, this);
101
102 constantPoolCacheKlassHandle = universeType.getOopField("_constantPoolCacheKlassObj").getValue();
103 constantPoolCacheKlassObj = new ConstantPoolCacheKlass(constantPoolCacheKlassHandle, this);
104
105 klassKlassHandle = universeType.getOopField("_klassKlassObj").getValue();
106 klassKlassObj = new KlassKlass(klassKlassHandle, this);
107
108 arrayKlassKlassHandle = universeType.getOopField("_arrayKlassKlassObj").getValue();
109 arrayKlassKlassObj = new ArrayKlassKlass(arrayKlassKlassHandle, this);
110
111 instanceKlassKlassHandle = universeType.getOopField("_instanceKlassKlassObj").getValue();
112 instanceKlassKlassObj = new InstanceKlassKlass(instanceKlassKlassHandle, this);
113
114 typeArrayKlassKlassHandle = universeType.getOopField("_typeArrayKlassKlassObj").getValue();
115 typeArrayKlassKlassObj = new TypeArrayKlassKlass(typeArrayKlassKlassHandle, this);
116
117 objArrayKlassKlassHandle = universeType.getOopField("_objArrayKlassKlassObj").getValue();
118 objArrayKlassKlassObj = new ObjArrayKlassKlass(objArrayKlassKlassHandle, this);
119
120 boolArrayKlassHandle = universeType.getOopField("_boolArrayKlassObj").getValue();
121 boolArrayKlassObj = new TypeArrayKlass(boolArrayKlassHandle, this);
122
123 byteArrayKlassHandle = universeType.getOopField("_byteArrayKlassObj").getValue();
124 byteArrayKlassObj = new TypeArrayKlass(byteArrayKlassHandle, this);
125
126 charArrayKlassHandle = universeType.getOopField("_charArrayKlassObj").getValue();
127 charArrayKlassObj = new TypeArrayKlass(charArrayKlassHandle, this);
128
129 intArrayKlassHandle = universeType.getOopField("_intArrayKlassObj").getValue();
130 intArrayKlassObj = new TypeArrayKlass(intArrayKlassHandle, this);
131
132 shortArrayKlassHandle = universeType.getOopField("_shortArrayKlassObj").getValue();
133 shortArrayKlassObj = new TypeArrayKlass(shortArrayKlassHandle, this);
134
135 longArrayKlassHandle = universeType.getOopField("_longArrayKlassObj").getValue();
136 longArrayKlassObj = new TypeArrayKlass(longArrayKlassHandle, this);
137
138 singleArrayKlassHandle = universeType.getOopField("_singleArrayKlassObj").getValue();
139 singleArrayKlassObj = new TypeArrayKlass(singleArrayKlassHandle, this);
140
141 doubleArrayKlassHandle = universeType.getOopField("_doubleArrayKlassObj").getValue();
142 doubleArrayKlassObj = new TypeArrayKlass(doubleArrayKlassHandle, this);
143
144 if (!VM.getVM().isCore()) {
145 methodDataKlassHandle = universeType.getOopField("_methodDataKlassObj").getValue();
146 methodDataKlassObj = new MethodDataKlass(methodDataKlassHandle, this);
147
148 compiledICHolderKlassHandle = universeType.getOopField("_compiledICHolderKlassObj").getValue();
149 compiledICHolderKlassObj= new CompiledICHolderKlass(compiledICHolderKlassHandle ,this);
150 }
151 }
152
153 public ObjectHeap(TypeDataBase db) throws WrongTypeException {
154 // Get commonly used sizes of basic types
155 oopSize = db.getOopSize();
156 byteSize = db.getJByteType().getSize();
157 charSize = db.getJCharType().getSize();
158 booleanSize = db.getJBooleanType().getSize();
159 intSize = db.getJIntType().getSize();
160 shortSize = db.getJShortType().getSize();
161 longSize = db.getJLongType().getSize();
162 floatSize = db.getJFloatType().getSize();
163 doubleSize = db.getJDoubleType().getSize();
164
165 initialize(db);
166 }
167
168 /** Comparison operation for oops, either or both of which may be null */
169 public boolean equal(Oop o1, Oop o2) {
170 if (o1 != null) return o1.equals(o2);
171 return (o2 == null);
172 }
173
174 // Cached sizes of basic types
175 private long oopSize;
176 private long byteSize;
177 private long charSize;
178 private long booleanSize;
179 private long intSize;
180 private long shortSize;
181 private long longSize;
182 private long floatSize;
183 private long doubleSize;
184
185 public long getOopSize() { return oopSize; }
186 public long getByteSize() { return byteSize; }
187 public long getCharSize() { return charSize; }
188 public long getBooleanSize() { return booleanSize; }
189 public long getIntSize() { return intSize; }
190 public long getShortSize() { return shortSize; }
191 public long getLongSize() { return longSize; }
192 public long getFloatSize() { return floatSize; }
193 public long getDoubleSize() { return doubleSize; }
194
195 // Accessors for well-known system classes (from Universe)
196 public SymbolKlass getSymbolKlassObj() { return symbolKlassObj; }
197 public MethodKlass getMethodKlassObj() { return methodKlassObj; }
198 public ConstMethodKlass getConstMethodKlassObj() { return constMethodKlassObj; }
199 public MethodDataKlass getMethodDataKlassObj() { return methodDataKlassObj; }
200 public ConstantPoolKlass getConstantPoolKlassObj() { return constantPoolKlassObj; }
201 public ConstantPoolCacheKlass getConstantPoolCacheKlassObj() { return constantPoolCacheKlassObj; }
202 public KlassKlass getKlassKlassObj() { return klassKlassObj; }
203 public ArrayKlassKlass getArrayKlassKlassObj() { return arrayKlassKlassObj; }
204 public InstanceKlassKlass getInstanceKlassKlassObj() { return instanceKlassKlassObj; }
205 public ObjArrayKlassKlass getObjArrayKlassKlassObj() { return objArrayKlassKlassObj; }
206 public TypeArrayKlassKlass getTypeArrayKlassKlassObj() { return typeArrayKlassKlassObj; }
207 public TypeArrayKlass getBoolArrayKlassObj() { return boolArrayKlassObj; }
208 public TypeArrayKlass getByteArrayKlassObj() { return byteArrayKlassObj; }
209 public TypeArrayKlass getCharArrayKlassObj() { return charArrayKlassObj; }
210 public TypeArrayKlass getIntArrayKlassObj() { return intArrayKlassObj; }
211 public TypeArrayKlass getShortArrayKlassObj() { return shortArrayKlassObj; }
212 public TypeArrayKlass getLongArrayKlassObj() { return longArrayKlassObj; }
213 public TypeArrayKlass getSingleArrayKlassObj() { return singleArrayKlassObj; }
214 public TypeArrayKlass getDoubleArrayKlassObj() { return doubleArrayKlassObj; }
215 public CompiledICHolderKlass getCompiledICHolderKlassObj() {
216 if (Assert.ASSERTS_ENABLED) {
217 Assert.that(!VM.getVM().isCore(), "must not be called for core build");
218 }
219 return compiledICHolderKlassObj;
220 }
221
222 /** Takes a BasicType and returns the corresponding primitive array
223 klass */
224 public Klass typeArrayKlassObj(int t) {
225 if (t == BasicType.getTBoolean()) return getBoolArrayKlassObj();
226 if (t == BasicType.getTChar()) return getCharArrayKlassObj();
227 if (t == BasicType.getTFloat()) return getSingleArrayKlassObj();
228 if (t == BasicType.getTDouble()) return getDoubleArrayKlassObj();
229 if (t == BasicType.getTByte()) return getByteArrayKlassObj();
230 if (t == BasicType.getTShort()) return getShortArrayKlassObj();
231 if (t == BasicType.getTInt()) return getIntArrayKlassObj();
232 if (t == BasicType.getTLong()) return getLongArrayKlassObj();
233 throw new RuntimeException("Illegal basic type " + t);
234 }
235
236 /** an interface to filter objects while walking heap */
237 public static interface ObjectFilter {
238 public boolean canInclude(Oop obj);
239 }
240
241 /** The base heap iteration mechanism */
242 public void iterate(HeapVisitor visitor) {
243 iterateLiveRegions(collectLiveRegions(), visitor, null);
244 }
245
246 /** iterate objects satisfying a specified ObjectFilter */
247 public void iterate(HeapVisitor visitor, ObjectFilter of) {
248 iterateLiveRegions(collectLiveRegions(), visitor, of);
249 }
250
251 /** iterate objects of given Klass. param 'includeSubtypes' tells whether to
252 * include objects of subtypes or not */
253 public void iterateObjectsOfKlass(HeapVisitor visitor, final Klass k, boolean includeSubtypes) {
254 if (includeSubtypes) {
255 if (k.isFinal()) {
256 // do the simpler "exact" klass loop
257 iterateExact(visitor, k);
258 } else {
259 iterateSubtypes(visitor, k);
260 }
261 } else {
262 // there can no object of abstract classes and interfaces
263 if (!k.isAbstract() && !k.isInterface()) {
264 iterateExact(visitor, k);
265 }
266 }
267 }
268
269 /** iterate objects of given Klass (objects of subtypes included) */
270 public void iterateObjectsOfKlass(HeapVisitor visitor, final Klass k) {
271 iterateObjectsOfKlass(visitor, k, true);
272 }
273
274 /** This routine can be used to iterate through the heap at an
275 extremely low level (stepping word-by-word) to provide the
276 ability to do very low-level debugging */
277 public void iterateRaw(RawHeapVisitor visitor) {
278 List liveRegions = collectLiveRegions();
279
280 // Summarize size
281 long totalSize = 0;
282 for (int i = 0; i < liveRegions.size(); i += 2) {
283 Address bottom = (Address) liveRegions.get(i);
284 Address top = (Address) liveRegions.get(i+1);
285 totalSize += top.minus(bottom);
286 }
287 visitor.prologue(totalSize);
288
289 for (int i = 0; i < liveRegions.size(); i += 2) {
290 Address bottom = (Address) liveRegions.get(i);
291 Address top = (Address) liveRegions.get(i+1);
292
293 // Traverses the space from bottom to top
294 while (bottom.lessThan(top)) {
295 visitor.visitAddress(bottom);
296 bottom = bottom.addOffsetTo(VM.getVM().getAddressSize());
297 }
298 }
299
300 visitor.epilogue();
301 }
302
303 // Iterates through only the perm generation for the purpose of
304 // finding static fields for liveness analysis
305 public void iteratePerm(HeapVisitor visitor) {
306 CollectedHeap heap = VM.getVM().getUniverse().heap();
307 List liveRegions = new ArrayList();
308 addPermGenLiveRegions(liveRegions, heap);
309 sortLiveRegions(liveRegions);
310 iterateLiveRegions(liveRegions, visitor, null);
311 }
312
313 // Creates an instance from the Oop hierarchy based based on the handle
314 public Oop newOop(OopHandle handle) {
315 // The only known way to detect the right type of an oop is
316 // traversing the class chain until a well-known klass is recognized.
317 // A more direct solution would require the klasses to expose
318 // the C++ vtbl structure.
319
320 // Handle the null reference
321 if (handle == null) return null;
322
323 // First check if handle is one of the root objects
324 if (handle.equals(methodKlassHandle)) return getMethodKlassObj();
325 if (handle.equals(constMethodKlassHandle)) return getConstMethodKlassObj();
326 if (handle.equals(symbolKlassHandle)) return getSymbolKlassObj();
327 if (handle.equals(constantPoolKlassHandle)) return getConstantPoolKlassObj();
328 if (handle.equals(constantPoolCacheKlassHandle)) return getConstantPoolCacheKlassObj();
329 if (handle.equals(instanceKlassKlassHandle)) return getInstanceKlassKlassObj();
330 if (handle.equals(objArrayKlassKlassHandle)) return getObjArrayKlassKlassObj();
331 if (handle.equals(klassKlassHandle)) return getKlassKlassObj();
332 if (handle.equals(arrayKlassKlassHandle)) return getArrayKlassKlassObj();
333 if (handle.equals(typeArrayKlassKlassHandle)) return getTypeArrayKlassKlassObj();
334 if (handle.equals(boolArrayKlassHandle)) return getBoolArrayKlassObj();
335 if (handle.equals(byteArrayKlassHandle)) return getByteArrayKlassObj();
336 if (handle.equals(charArrayKlassHandle)) return getCharArrayKlassObj();
337 if (handle.equals(intArrayKlassHandle)) return getIntArrayKlassObj();
338 if (handle.equals(shortArrayKlassHandle)) return getShortArrayKlassObj();
339 if (handle.equals(longArrayKlassHandle)) return getLongArrayKlassObj();
340 if (handle.equals(singleArrayKlassHandle)) return getSingleArrayKlassObj();
341 if (handle.equals(doubleArrayKlassHandle)) return getDoubleArrayKlassObj();
342 if (!VM.getVM().isCore()) {
343 if (handle.equals(compiledICHolderKlassHandle)) return getCompiledICHolderKlassObj();
344 if (handle.equals(methodDataKlassHandle)) return getMethodDataKlassObj();
345 }
346
347 // Then check if obj.klass() is one of the root objects
348 OopHandle klass = Oop.getKlassForOopHandle(handle);
349 if (klass != null) {
350 if (klass.equals(methodKlassHandle)) return new Method(handle, this);
351 if (klass.equals(constMethodKlassHandle)) return new ConstMethod(handle, this);
352 if (klass.equals(symbolKlassHandle)) return new Symbol(handle, this);
353 if (klass.equals(constantPoolKlassHandle)) return new ConstantPool(handle, this);
354 if (klass.equals(constantPoolCacheKlassHandle)) return new ConstantPoolCache(handle, this);
355 if (!VM.getVM().isCore()) {
356 if (klass.equals(compiledICHolderKlassHandle)) return new CompiledICHolder(handle, this);
357 if (klass.equals(methodDataKlassHandle)) return new MethodData(handle, this);
358 }
359 if (klass.equals(instanceKlassKlassHandle)) return new InstanceKlass(handle, this);
360 if (klass.equals(objArrayKlassKlassHandle)) return new ObjArrayKlass(handle, this);
361 if (klass.equals(typeArrayKlassKlassHandle)) return new TypeArrayKlass(handle, this);
362
363 // Lastly check if obj.klass().klass() is on of the root objects
364 OopHandle klassKlass = Oop.getKlassForOopHandle(klass);
365 if (klassKlass != null) {
366 if (klassKlass.equals(instanceKlassKlassHandle)) return new Instance(handle, this);
367 if (klassKlass.equals(objArrayKlassKlassHandle)) return new ObjArray(handle, this);
368 if (klassKlass.equals(typeArrayKlassKlassHandle)) return new TypeArray(handle, this);
369 }
370 }
371
372 System.err.println("Unknown oop at " + handle);
373 System.err.println("Oop's klass is " + klass);
374
375 throw new UnknownOopException();
376 }
377
378 // Print all objects in the object heap
379 public void print() {
380 HeapPrinter printer = new HeapPrinter(System.out);
381 iterate(printer);
382 }
383
384 //---------------------------------------------------------------------------
385 // Internals only below this point
386 //
387
388 private void iterateExact(HeapVisitor visitor, final Klass k) {
389 iterateLiveRegions(collectLiveRegions(), visitor, new ObjectFilter() {
390 public boolean canInclude(Oop obj) {
391 Klass tk = obj.getKlass();
392 // null Klass is seen sometimes!
393 return (tk != null && tk.equals(k));
394 }
395 });
396 }
397
398 private void iterateSubtypes(HeapVisitor visitor, final Klass k) {
399 iterateLiveRegions(collectLiveRegions(), visitor, new ObjectFilter() {
400 public boolean canInclude(Oop obj) {
401 Klass tk = obj.getKlass();
402 // null Klass is seen sometimes!
403 return (tk != null && tk.isSubtypeOf(k));
404 }
405 });
406 }
407
408 private void iterateLiveRegions(List liveRegions, HeapVisitor visitor, ObjectFilter of) {
409 // Summarize size
410 long totalSize = 0;
411 for (int i = 0; i < liveRegions.size(); i += 2) {
412 Address bottom = (Address) liveRegions.get(i);
413 Address top = (Address) liveRegions.get(i+1);
414 totalSize += top.minus(bottom);
415 }
416 visitor.prologue(totalSize);
417
418 CompactibleFreeListSpace cmsSpaceOld = null;
419 CompactibleFreeListSpace cmsSpacePerm = null;
420 CollectedHeap heap = VM.getVM().getUniverse().heap();
421
422 if (heap instanceof GenCollectedHeap) {
423 GenCollectedHeap genHeap = (GenCollectedHeap) heap;
424 Generation genOld = genHeap.getGen(1);
425 Generation genPerm = genHeap.permGen();
426 if (genOld instanceof ConcurrentMarkSweepGeneration) {
427 ConcurrentMarkSweepGeneration concGen = (ConcurrentMarkSweepGeneration)genOld;
428 cmsSpaceOld = concGen.cmsSpace();
429 }
430 if (genPerm instanceof ConcurrentMarkSweepGeneration) {
431 ConcurrentMarkSweepGeneration concGen = (ConcurrentMarkSweepGeneration)genPerm;
432 cmsSpacePerm = concGen.cmsSpace();
433 }
434 }
435
436 for (int i = 0; i < liveRegions.size(); i += 2) {
437 Address bottom = (Address) liveRegions.get(i);
438 Address top = (Address) liveRegions.get(i+1);
439
440 try {
441 // Traverses the space from bottom to top
442 OopHandle handle = bottom.addOffsetToAsOopHandle(0);
443 while (handle.lessThan(top)) {
444 Oop obj = null;
445
446 try {
447 obj = newOop(handle);
448 } catch (UnknownOopException exp) {
449 }
450 if (obj == null) {
451 //Find the object size using Printezis bits and skip over
452 System.err.println("Finding object size using Printezis bits and skipping over...");
453 long size = 0;
454
455 if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ){
456 size = cmsSpaceOld.collector().blockSizeUsingPrintezisBits(handle);
457 } else if ((cmsSpacePerm != null) && cmsSpacePerm.contains(handle) ){
458 size = cmsSpacePerm.collector().blockSizeUsingPrintezisBits(handle);
459 }
460
461 if (size <= 0) {
462 //Either Printezis bits not set or handle is not in cms space.
463 throw new UnknownOopException();
464 }
465
466 handle = handle.addOffsetToAsOopHandle(CompactibleFreeListSpace.adjustObjectSizeInBytes(size));
467 continue;
468 }
469 if (of == null || of.canInclude(obj)) {
470 if (visitor.doObj(obj)) {
471 // doObj() returns true to abort this loop.
472 break;
473 }
474 }
475 if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ||
476 (cmsSpacePerm != null) && cmsSpacePerm.contains(handle) ) {
477 handle = handle.addOffsetToAsOopHandle(CompactibleFreeListSpace.adjustObjectSizeInBytes(obj.getObjectSize()) );
478 } else {
479 handle = handle.addOffsetToAsOopHandle(obj.getObjectSize());
480 }
481 }
482 }
483 catch (AddressException e) {
484 // This is okay at the top of these regions
485 }
486 catch (UnknownOopException e) {
487 // This is okay at the top of these regions
488 }
489 }
490
491 visitor.epilogue();
492 }
493
494 private void addPermGenLiveRegions(List output, CollectedHeap heap) {
495 LiveRegionsCollector lrc = new LiveRegionsCollector(output);
496 if (heap instanceof GenCollectedHeap) {
497 GenCollectedHeap genHeap = (GenCollectedHeap) heap;
498 Generation gen = genHeap.permGen();
499 gen.spaceIterate(lrc, true);
500 } else if (heap instanceof ParallelScavengeHeap) {
501 ParallelScavengeHeap psh = (ParallelScavengeHeap) heap;
502 PSPermGen permGen = psh.permGen();
503 addLiveRegions(permGen.objectSpace().getLiveRegions(), output);
504 } else {
505 if (Assert.ASSERTS_ENABLED) {
506 Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " +
507 heap.getClass().getName());
508 }
509 }
510 }
511
512 private void addLiveRegions(List input, List output) {
513 for (Iterator itr = input.iterator(); itr.hasNext();) {
514 MemRegion reg = (MemRegion) itr.next();
515 Address top = reg.end();
516 Address bottom = reg.start();
517 if (Assert.ASSERTS_ENABLED) {
518 Assert.that(top != null, "top address in a live region should not be null");
519 }
520 if (Assert.ASSERTS_ENABLED) {
521 Assert.that(bottom != null, "bottom address in a live region should not be null");
522 }
523 output.add(top);
524 output.add(bottom);
525 }
526 }
527
528 private class LiveRegionsCollector implements SpaceClosure {
529 LiveRegionsCollector(List l) {
530 liveRegions = l;
531 }
532
533 public void doSpace(Space s) {
534 addLiveRegions(s.getLiveRegions(), liveRegions);
535 }
536 private List liveRegions;
537 }
538
539 // Returns a List<Address> where the addresses come in pairs. These
540 // designate the live regions of the heap.
541 private List collectLiveRegions() {
542 // We want to iterate through all live portions of the heap, but
543 // do not want to abort the heap traversal prematurely if we find
544 // a problem (like an allocated but uninitialized object at the
545 // top of a generation). To do this we enumerate all generations'
546 // bottom and top regions, and factor in TLABs if necessary.
547
548 // List<Address>. Addresses come in pairs.
549 List liveRegions = new ArrayList();
550 LiveRegionsCollector lrc = new LiveRegionsCollector(liveRegions);
551
552 CollectedHeap heap = VM.getVM().getUniverse().heap();
553
554 if (heap instanceof GenCollectedHeap) {
555 GenCollectedHeap genHeap = (GenCollectedHeap) heap;
556 // Run through all generations, obtaining bottom-top pairs.
557 for (int i = 0; i < genHeap.nGens(); i++) {
558 Generation gen = genHeap.getGen(i);
559 gen.spaceIterate(lrc, true);
560 }
561 } else if (heap instanceof ParallelScavengeHeap) {
562 ParallelScavengeHeap psh = (ParallelScavengeHeap) heap;
563 PSYoungGen youngGen = psh.youngGen();
564 // Add eden space
565 addLiveRegions(youngGen.edenSpace().getLiveRegions(), liveRegions);
566 // Add from-space but not to-space
567 addLiveRegions(youngGen.fromSpace().getLiveRegions(), liveRegions);
568 PSOldGen oldGen = psh.oldGen();
569 addLiveRegions(oldGen.objectSpace().getLiveRegions(), liveRegions);
570 } else {
571 if (Assert.ASSERTS_ENABLED) {
572 Assert.that(false, "Expecting GenCollectedHeap or ParallelScavengeHeap, but got " +
573 heap.getClass().getName());
574 }
575 }
576
577 // handle perm generation
578 addPermGenLiveRegions(liveRegions, heap);
579
580 // If UseTLAB is enabled, snip out regions associated with TLABs'
581 // dead regions. Note that TLABs can be present in any generation.
582
583 // FIXME: consider adding fewer boundaries to live region list.
584 // Theoretically only need to stop at TLAB's top and resume at its
585 // end.
586
587 if (VM.getVM().getUseTLAB()) {
588 for (JavaThread thread = VM.getVM().getThreads().first(); thread != null; thread = thread.next()) {
589 if (thread.isJavaThread()) {
590 ThreadLocalAllocBuffer tlab = thread.tlab();
591 if (tlab.start() != null) {
592 if ((tlab.top() == null) || (tlab.end() == null)) {
593 System.err.print("Warning: skipping invalid TLAB for thread ");
594 thread.printThreadIDOn(System.err);
595 System.err.println();
596 } else {
597 // Go from:
598 // - below start() to start()
599 // - start() to top()
600 // - end() and above
601 liveRegions.add(tlab.start());
602 liveRegions.add(tlab.start());
603 liveRegions.add(tlab.top());
604 liveRegions.add(tlab.end());
605 }
606 }
607 }
608 }
609 }
610
611 // Now sort live regions
612 sortLiveRegions(liveRegions);
613
614 if (Assert.ASSERTS_ENABLED) {
615 Assert.that(liveRegions.size() % 2 == 0, "Must have even number of region boundaries");
616 }
617
618 return liveRegions;
619 }
620
621 private void sortLiveRegions(List liveRegions) {
622 Collections.sort(liveRegions, new Comparator() {
623 public int compare(Object o1, Object o2) {
624 Address a1 = (Address) o1;
625 Address a2 = (Address) o2;
626 if (AddressOps.lt(a1, a2)) {
627 return -1;
628 } else if (AddressOps.gt(a1, a2)) {
629 return 1;
630 }
631 return 0;
632 }
633 });
634 }
635 }