0
|
1 /*
|
|
2 * Copyright 2003-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 package sun.jvm.hotspot.memory;
|
|
26
|
|
27 import java.io.*;
|
|
28 import java.util.*;
|
|
29 import sun.jvm.hotspot.debugger.*;
|
|
30 import sun.jvm.hotspot.oops.*;
|
|
31 import sun.jvm.hotspot.runtime.*;
|
|
32 import sun.jvm.hotspot.types.*;
|
|
33 import sun.jvm.hotspot.utilities.*;
|
|
34
|
|
35 public class CompactibleFreeListSpace extends CompactibleSpace {
|
|
36 private static AddressField collectorField;
|
|
37
|
|
38 static {
|
|
39 VM.registerVMInitializedObserver(new Observer() {
|
|
40 public void update(Observable o, Object data) {
|
|
41 initialize(VM.getVM().getTypeDataBase());
|
|
42 }
|
|
43 });
|
|
44 }
|
|
45
|
|
46 private static synchronized void initialize(TypeDataBase db) {
|
|
47 long sizeofFreeChunk = db.lookupType("FreeChunk").getSize();
|
|
48 VM vm = VM.getVM();
|
|
49 MinChunkSizeInBytes = numQuanta(sizeofFreeChunk, vm.getMinObjAlignmentInBytes()) *
|
|
50 vm.getMinObjAlignmentInBytes();
|
|
51
|
|
52 Type type = db.lookupType("CompactibleFreeListSpace");
|
|
53 collectorField = type.getAddressField("_collector");
|
|
54 }
|
|
55
|
|
56 public CompactibleFreeListSpace(Address addr) {
|
|
57 super(addr);
|
|
58 }
|
|
59
|
|
60 // Accessing block offset table
|
|
61 public CMSCollector collector() {
|
|
62 return (CMSCollector) VMObjectFactory.newObject(
|
|
63 CMSCollector.class,
|
|
64 collectorField.getValue(addr));
|
|
65 }
|
|
66
|
|
67 public long used() {
|
|
68 List regions = getLiveRegions();
|
|
69 long usedSize = 0L;
|
|
70 for (Iterator itr = regions.iterator(); itr.hasNext();) {
|
|
71 MemRegion mr = (MemRegion) itr.next();
|
|
72 usedSize += mr.byteSize();
|
|
73 }
|
|
74 return usedSize;
|
|
75 }
|
|
76
|
|
77 public long free() {
|
|
78 return capacity() - used();
|
|
79 }
|
|
80
|
|
81 public void printOn(PrintStream tty) {
|
|
82 tty.print("free-list-space");
|
|
83 }
|
|
84
|
|
85 public Address skipBlockSizeUsingPrintezisBits(Address pos) {
|
|
86 CMSCollector collector = collector();
|
|
87 long size = 0;
|
|
88 Address addr = null;
|
|
89
|
|
90 if (collector != null) {
|
|
91 size = collector.blockSizeUsingPrintezisBits(pos);
|
|
92 if (size >= 3) {
|
|
93 addr = pos.addOffsetTo(adjustObjectSizeInBytes(size));
|
|
94 }
|
|
95 }
|
|
96 return addr;
|
|
97 }
|
|
98
|
|
99 public List/*<MemRegion>*/ getLiveRegions() {
|
|
100 List res = new ArrayList(); // List<MemRegion>
|
|
101 VM vm = VM.getVM();
|
|
102 Debugger dbg = vm.getDebugger();
|
|
103 ObjectHeap heap = vm.getObjectHeap();
|
|
104 Address cur = bottom();
|
|
105 Address regionStart = cur;
|
|
106 Address limit = end();
|
|
107 final long addressSize = vm.getAddressSize();
|
|
108
|
|
109 for (; cur.lessThan(limit);) {
|
|
110 Address klassOop = cur.getAddressAt(addressSize);
|
|
111 // FIXME: need to do a better job here.
|
|
112 // can I use bitMap here?
|
|
113 if (klassOop == null) {
|
|
114 //Find the object size using Printezis bits and skip over
|
|
115 System.err.println("Finding object size using Printezis bits and skipping over...");
|
|
116 long size = collector().blockSizeUsingPrintezisBits(cur);
|
|
117 if (size == -1) {
|
|
118 System.err.println("Printezis bits not set...");
|
|
119 break;
|
|
120 }
|
|
121 cur = cur.addOffsetTo(adjustObjectSizeInBytes(size));
|
|
122 }
|
|
123
|
187
|
124 if (FreeChunk.indicatesFreeChunk(cur)) {
|
0
|
125 if (! cur.equals(regionStart)) {
|
|
126 res.add(new MemRegion(regionStart, cur));
|
|
127 }
|
|
128 FreeChunk fc = (FreeChunk) VMObjectFactory.newObject(FreeChunk.class, cur);
|
|
129 long chunkSize = fc.size();
|
|
130 if (Assert.ASSERTS_ENABLED) {
|
|
131 Assert.that(chunkSize > 0, "invalid FreeChunk size");
|
|
132 }
|
|
133 // note that fc.size() gives chunk size in heap words
|
|
134 cur = cur.addOffsetTo(chunkSize * addressSize);
|
|
135 System.err.println("Free chunk in CMS heap, size="+chunkSize * addressSize);
|
|
136 regionStart = cur;
|
|
137 } else if (klassOop != null) {
|
|
138 Oop obj = heap.newOop(cur.addOffsetToAsOopHandle(0));
|
|
139 long objectSize = obj.getObjectSize();
|
|
140 cur = cur.addOffsetTo(adjustObjectSizeInBytes(objectSize));
|
|
141 }
|
|
142 }
|
|
143 return res;
|
|
144 }
|
|
145
|
|
146 //-- Internals only below this point
|
|
147
|
|
148 // Unlike corresponding VM code, we operate on byte size rather than
|
|
149 // HeapWord size for convenience.
|
|
150
|
|
151 private static long numQuanta(long x, long y) {
|
|
152 return ((x+y-1)/y);
|
|
153 }
|
|
154
|
|
155 public static long adjustObjectSizeInBytes(long sizeInBytes) {
|
|
156 return Oop.alignObjectSize(Math.max(sizeInBytes, MinChunkSizeInBytes));
|
|
157 }
|
|
158
|
|
159 // FIXME: should I read this directly from VM?
|
|
160 private static long MinChunkSizeInBytes;
|
|
161 }
|