1 /* 2 * Copyright (c) 2003, 2013, 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 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 // for free size, three fields 39 // FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks 40 // FreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks 41 // LinearAllocBlock _smallLinearAllocBlock; // small linear alloc in TLAB 42 private static AddressField indexedFreeListField; 43 private static AddressField dictionaryField; 44 private static long smallLinearAllocBlockFieldOffset; 45 private static long indexedFreeListSizeOf; 46 47 private int heapWordSize; // 4 for 32bit, 8 for 64 bits 48 private int IndexSetStart; // for small indexed list 49 private int IndexSetSize; 50 private int IndexSetStride; 51 52 static { 53 VM.registerVMInitializedObserver(new Observer() { 54 public void update(Observable o, Object data) { 55 initialize(VM.getVM().getTypeDataBase()); 56 } 57 }); 58 } 59 60 private static synchronized void initialize(TypeDataBase db) { 61 long sizeofFreeChunk = db.lookupType("FreeChunk").getSize(); 62 VM vm = VM.getVM(); 63 MinChunkSizeInBytes = numQuanta(sizeofFreeChunk, vm.getMinObjAlignmentInBytes()) * 64 vm.getMinObjAlignmentInBytes(); 65 66 Type type = db.lookupType("CompactibleFreeListSpace"); 67 collectorField = type.getAddressField("_collector"); 68 collectorField = type.getAddressField("_collector"); 69 dictionaryField = type.getAddressField("_dictionary"); 70 indexedFreeListField = type.getAddressField("_indexedFreeList[0]"); 71 smallLinearAllocBlockFieldOffset = type.getField("_smallLinearAllocBlock").getOffset(); 72 } 73 74 public CompactibleFreeListSpace(Address addr) { 75 super(addr); 76 VM vm = VM.getVM(); 77 heapWordSize = vm.getHeapWordSize(); 78 IndexSetStart = vm.getMinObjAlignmentInBytes() / heapWordSize; 79 IndexSetStride = IndexSetStart; 80 IndexSetSize = 257; 81 } 82 83 // Accessing block offset table 84 public CMSCollector collector() { 85 return (CMSCollector) VMObjectFactory.newObject( 86 CMSCollector.class, 87 collectorField.getValue(addr)); 88 } 89 90 public long free0() { 91 return capacity() - used0(); 92 } 93 94 public long used() { 95 return capacity() - free(); 96 } 97 98 public long used0() { 99 List regions = getLiveRegions(); 100 long usedSize = 0L; 101 for (Iterator itr = regions.iterator(); itr.hasNext();) { 102 MemRegion mr = (MemRegion) itr.next(); 103 usedSize += mr.byteSize(); 104 } 105 return usedSize; 106 } 107 108 public long free() { 109 // small chunks 110 long size = 0; 111 Address cur = addr.addOffsetTo( indexedFreeListField.getOffset() ); 112 cur = cur.addOffsetTo(IndexSetStart*FreeList.sizeOf()); 113 for (int i=IndexSetStart; i<IndexSetSize; i += IndexSetStride) { 114 FreeList freeList = (FreeList) VMObjectFactory.newObject(FreeList.class, cur); 115 size += i*freeList.count(); 116 cur= cur.addOffsetTo(IndexSetStride*FreeList.sizeOf()); 117 } 118 119 // large block 120 AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class, 121 dictionaryField.getValue(addr)); 122 size += aflbd.size(); 123 124 125 // linear block in TLAB 126 LinearAllocBlock lab = (LinearAllocBlock) VMObjectFactory.newObject(LinearAllocBlock.class, 127 addr.addOffsetTo(smallLinearAllocBlockFieldOffset)); 128 size += lab.word_size(); 129 130 return size*heapWordSize; 131 } 132 133 public void printOn(PrintStream tty) { 134 tty.print("free-list-space"); 135 tty.print("[ " + bottom() + " , " + end() + " ) "); 136 long cap = capacity(); 137 long used_size = used(); 138 long free_size = free(); 139 int used_perc = (int)((double)used_size/cap*100); 140 tty.print("space capacity = " + cap + " used(" + used_perc + "%)= " + used_size + " "); 141 tty.print("free= " + free_size ); 142 tty.print("\n"); 143 144 } 145 146 public Address skipBlockSizeUsingPrintezisBits(Address pos) { 147 CMSCollector collector = collector(); 148 long size = 0; 149 Address addr = null; 150 151 if (collector != null) { 152 size = collector.blockSizeUsingPrintezisBits(pos); 153 if (size >= 3) { 154 addr = pos.addOffsetTo(adjustObjectSizeInBytes(size)); 155 } 156 } 157 return addr; 158 } 159 160 public List/*<MemRegion>*/ getLiveRegions() { 161 List res = new ArrayList(); // List<MemRegion> 162 VM vm = VM.getVM(); 163 Debugger dbg = vm.getDebugger(); 164 ObjectHeap heap = vm.getObjectHeap(); 165 Address cur = bottom(); 166 Address regionStart = cur; 167 Address limit = end(); 168 final long addressSize = vm.getAddressSize(); 169 170 for (; cur.lessThan(limit);) { 171 Address k = cur.getAddressAt(addressSize); 172 if (FreeChunk.indicatesFreeChunk(cur)) { 173 if (! cur.equals(regionStart)) { 174 res.add(new MemRegion(regionStart, cur)); 175 } 176 FreeChunk fc = (FreeChunk) VMObjectFactory.newObject(FreeChunk.class, cur); 177 long chunkSize = fc.size(); 178 if (Assert.ASSERTS_ENABLED) { 179 Assert.that(chunkSize > 0, "invalid FreeChunk size"); 180 } 181 // note that fc.size() gives chunk size in heap words 182 cur = cur.addOffsetTo(chunkSize * addressSize); 183 regionStart = cur; 184 } else if (k != null) { 185 Oop obj = heap.newOop(cur.addOffsetToAsOopHandle(0)); 186 long objectSize = obj.getObjectSize(); 187 cur = cur.addOffsetTo(adjustObjectSizeInBytes(objectSize)); 188 } else { 189 // FIXME: need to do a better job here. 190 // can I use bitMap here? 191 //Find the object size using Printezis bits and skip over 192 long size = collector().blockSizeUsingPrintezisBits(cur); 193 if (size == -1) { 194 break; 195 } 196 cur = cur.addOffsetTo(adjustObjectSizeInBytes(size)); 197 } 198 } 199 return res; 200 } 201 202 //-- Internals only below this point 203 204 // Unlike corresponding VM code, we operate on byte size rather than 205 // HeapWord size for convenience. 206 207 private static long numQuanta(long x, long y) { 208 return ((x+y-1)/y); 209 } 210 211 public static long adjustObjectSizeInBytes(long sizeInBytes) { 212 return Oop.alignObjectSize(Math.max(sizeInBytes, MinChunkSizeInBytes)); 213 } 214 215 // FIXME: should I read this directly from VM? 216 private static long MinChunkSizeInBytes; 217 }