agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java

Mon, 17 Feb 2014 09:51:37 +0100

author
sjohanss
date
Mon, 17 Feb 2014 09:51:37 +0100
changeset 7587
490b4cb2c0b5
parent 4600
49618582fc5b
child 7994
04ff2f6cd0eb
permissions
-rw-r--r--

8033440: jmap reports unexpected used/free size of concurrent mark-sweep generation
Summary: SA used the wrong type for the indexedFreeList in CompactibleFreeListSpace.
Reviewed-by: coleenp, dsamersoff

duke@435 1 /*
sjohanss@7587 2 * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 package sun.jvm.hotspot.memory;
duke@435 26
sjohanss@7587 27 import java.io.PrintStream;
sjohanss@7587 28 import java.util.ArrayList;
sjohanss@7587 29 import java.util.Iterator;
sjohanss@7587 30 import java.util.List;
sjohanss@7587 31 import java.util.Observable;
sjohanss@7587 32 import java.util.Observer;
sjohanss@7587 33
sjohanss@7587 34 import sun.jvm.hotspot.debugger.Address;
sjohanss@7587 35 import sun.jvm.hotspot.debugger.Debugger;
sjohanss@7587 36 import sun.jvm.hotspot.oops.ObjectHeap;
sjohanss@7587 37 import sun.jvm.hotspot.oops.Oop;
sjohanss@7587 38 import sun.jvm.hotspot.runtime.VM;
sjohanss@7587 39 import sun.jvm.hotspot.runtime.VMObjectFactory;
sjohanss@7587 40 import sun.jvm.hotspot.types.AddressField;
sjohanss@7587 41 import sun.jvm.hotspot.types.Type;
sjohanss@7587 42 import sun.jvm.hotspot.types.TypeDataBase;
sjohanss@7587 43 import sun.jvm.hotspot.utilities.Assert;
duke@435 44
duke@435 45 public class CompactibleFreeListSpace extends CompactibleSpace {
duke@435 46 private static AddressField collectorField;
dcubed@587 47 private static AddressField indexedFreeListField;
dcubed@587 48 private static AddressField dictionaryField;
dcubed@587 49 private static long smallLinearAllocBlockFieldOffset;
dcubed@587 50
dcubed@587 51 private int heapWordSize; // 4 for 32bit, 8 for 64 bits
dcubed@587 52 private int IndexSetStart; // for small indexed list
dcubed@587 53 private int IndexSetSize;
dcubed@587 54 private int IndexSetStride;
dcubed@587 55
duke@435 56 static {
duke@435 57 VM.registerVMInitializedObserver(new Observer() {
duke@435 58 public void update(Observable o, Object data) {
duke@435 59 initialize(VM.getVM().getTypeDataBase());
duke@435 60 }
duke@435 61 });
duke@435 62 }
duke@435 63
duke@435 64 private static synchronized void initialize(TypeDataBase db) {
duke@435 65 long sizeofFreeChunk = db.lookupType("FreeChunk").getSize();
duke@435 66 VM vm = VM.getVM();
duke@435 67 MinChunkSizeInBytes = numQuanta(sizeofFreeChunk, vm.getMinObjAlignmentInBytes()) *
duke@435 68 vm.getMinObjAlignmentInBytes();
duke@435 69
duke@435 70 Type type = db.lookupType("CompactibleFreeListSpace");
duke@435 71 collectorField = type.getAddressField("_collector");
dcubed@587 72 collectorField = type.getAddressField("_collector");
dcubed@587 73 dictionaryField = type.getAddressField("_dictionary");
dcubed@587 74 indexedFreeListField = type.getAddressField("_indexedFreeList[0]");
dcubed@587 75 smallLinearAllocBlockFieldOffset = type.getField("_smallLinearAllocBlock").getOffset();
duke@435 76 }
duke@435 77
duke@435 78 public CompactibleFreeListSpace(Address addr) {
duke@435 79 super(addr);
kvn@1926 80 VM vm = VM.getVM();
kvn@1926 81 heapWordSize = vm.getHeapWordSize();
kvn@1926 82 IndexSetStart = vm.getMinObjAlignmentInBytes() / heapWordSize;
kvn@1926 83 IndexSetStride = IndexSetStart;
kvn@1926 84 IndexSetSize = 257;
duke@435 85 }
duke@435 86
duke@435 87 // Accessing block offset table
duke@435 88 public CMSCollector collector() {
duke@435 89 return (CMSCollector) VMObjectFactory.newObject(
duke@435 90 CMSCollector.class,
duke@435 91 collectorField.getValue(addr));
dcubed@587 92 }
dcubed@587 93
dcubed@587 94 public long free0() {
dcubed@587 95 return capacity() - used0();
dcubed@587 96 }
duke@435 97
duke@435 98 public long used() {
dcubed@587 99 return capacity() - free();
dcubed@587 100 }
dcubed@587 101
dcubed@587 102 public long used0() {
duke@435 103 List regions = getLiveRegions();
duke@435 104 long usedSize = 0L;
duke@435 105 for (Iterator itr = regions.iterator(); itr.hasNext();) {
duke@435 106 MemRegion mr = (MemRegion) itr.next();
duke@435 107 usedSize += mr.byteSize();
duke@435 108 }
duke@435 109 return usedSize;
duke@435 110 }
duke@435 111
duke@435 112 public long free() {
dcubed@587 113 // small chunks
dcubed@587 114 long size = 0;
dcubed@587 115 Address cur = addr.addOffsetTo( indexedFreeListField.getOffset() );
sjohanss@7587 116 cur = cur.addOffsetTo(IndexSetStart*AdaptiveFreeList.sizeOf());
dcubed@587 117 for (int i=IndexSetStart; i<IndexSetSize; i += IndexSetStride) {
sjohanss@7587 118 AdaptiveFreeList freeList = (AdaptiveFreeList) VMObjectFactory.newObject(AdaptiveFreeList.class, cur);
dcubed@587 119 size += i*freeList.count();
sjohanss@7587 120 cur= cur.addOffsetTo(IndexSetStride*AdaptiveFreeList.sizeOf());
dcubed@587 121 }
dcubed@587 122
dcubed@587 123 // large block
minqi@4491 124 AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class,
dcubed@587 125 dictionaryField.getValue(addr));
minqi@4491 126 size += aflbd.size();
dcubed@587 127
dcubed@587 128
dcubed@587 129 // linear block in TLAB
dcubed@587 130 LinearAllocBlock lab = (LinearAllocBlock) VMObjectFactory.newObject(LinearAllocBlock.class,
dcubed@587 131 addr.addOffsetTo(smallLinearAllocBlockFieldOffset));
dcubed@587 132 size += lab.word_size();
dcubed@587 133
dcubed@587 134 return size*heapWordSize;
dcubed@587 135 }
duke@435 136
duke@435 137 public void printOn(PrintStream tty) {
duke@435 138 tty.print("free-list-space");
dcubed@587 139 tty.print("[ " + bottom() + " , " + end() + " ) ");
dcubed@587 140 long cap = capacity();
dcubed@587 141 long used_size = used();
dcubed@587 142 long free_size = free();
dcubed@587 143 int used_perc = (int)((double)used_size/cap*100);
dcubed@587 144 tty.print("space capacity = " + cap + " used(" + used_perc + "%)= " + used_size + " ");
dcubed@587 145 tty.print("free= " + free_size );
dcubed@587 146 tty.print("\n");
dcubed@587 147
duke@435 148 }
duke@435 149
duke@435 150 public Address skipBlockSizeUsingPrintezisBits(Address pos) {
duke@435 151 CMSCollector collector = collector();
duke@435 152 long size = 0;
duke@435 153 Address addr = null;
duke@435 154
duke@435 155 if (collector != null) {
duke@435 156 size = collector.blockSizeUsingPrintezisBits(pos);
duke@435 157 if (size >= 3) {
duke@435 158 addr = pos.addOffsetTo(adjustObjectSizeInBytes(size));
duke@435 159 }
duke@435 160 }
duke@435 161 return addr;
duke@435 162 }
duke@435 163
duke@435 164 public List/*<MemRegion>*/ getLiveRegions() {
duke@435 165 List res = new ArrayList(); // List<MemRegion>
duke@435 166 VM vm = VM.getVM();
duke@435 167 Debugger dbg = vm.getDebugger();
duke@435 168 ObjectHeap heap = vm.getObjectHeap();
duke@435 169 Address cur = bottom();
duke@435 170 Address regionStart = cur;
duke@435 171 Address limit = end();
duke@435 172 final long addressSize = vm.getAddressSize();
duke@435 173
duke@435 174 for (; cur.lessThan(limit);) {
coleenp@4037 175 Address k = cur.getAddressAt(addressSize);
coleenp@622 176 if (FreeChunk.indicatesFreeChunk(cur)) {
duke@435 177 if (! cur.equals(regionStart)) {
duke@435 178 res.add(new MemRegion(regionStart, cur));
duke@435 179 }
duke@435 180 FreeChunk fc = (FreeChunk) VMObjectFactory.newObject(FreeChunk.class, cur);
duke@435 181 long chunkSize = fc.size();
duke@435 182 if (Assert.ASSERTS_ENABLED) {
duke@435 183 Assert.that(chunkSize > 0, "invalid FreeChunk size");
duke@435 184 }
duke@435 185 // note that fc.size() gives chunk size in heap words
duke@435 186 cur = cur.addOffsetTo(chunkSize * addressSize);
duke@435 187 regionStart = cur;
coleenp@4037 188 } else if (k != null) {
duke@435 189 Oop obj = heap.newOop(cur.addOffsetToAsOopHandle(0));
duke@435 190 long objectSize = obj.getObjectSize();
duke@435 191 cur = cur.addOffsetTo(adjustObjectSizeInBytes(objectSize));
never@1339 192 } else {
never@1339 193 // FIXME: need to do a better job here.
never@1339 194 // can I use bitMap here?
never@1339 195 //Find the object size using Printezis bits and skip over
never@1339 196 long size = collector().blockSizeUsingPrintezisBits(cur);
never@1339 197 if (size == -1) {
never@1339 198 break;
never@1339 199 }
never@1339 200 cur = cur.addOffsetTo(adjustObjectSizeInBytes(size));
duke@435 201 }
duke@435 202 }
duke@435 203 return res;
duke@435 204 }
duke@435 205
duke@435 206 //-- Internals only below this point
duke@435 207
duke@435 208 // Unlike corresponding VM code, we operate on byte size rather than
duke@435 209 // HeapWord size for convenience.
duke@435 210
duke@435 211 private static long numQuanta(long x, long y) {
duke@435 212 return ((x+y-1)/y);
duke@435 213 }
duke@435 214
duke@435 215 public static long adjustObjectSizeInBytes(long sizeInBytes) {
duke@435 216 return Oop.alignObjectSize(Math.max(sizeInBytes, MinChunkSizeInBytes));
duke@435 217 }
duke@435 218
duke@435 219 // FIXME: should I read this directly from VM?
duke@435 220 private static long MinChunkSizeInBytes;
duke@435 221 }

mercurial