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.code; 26 27 import java.util.*; 28 import sun.jvm.hotspot.debugger.*; 29 import sun.jvm.hotspot.memory.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 public class CodeCache { 35 private static AddressField heapField; 36 private static AddressField scavengeRootNMethodsField; 37 private static VirtualConstructor virtualConstructor; 38 39 private CodeHeap heap; 40 41 static { 42 VM.registerVMInitializedObserver(new Observer() { 43 public void update(Observable o, Object data) { 44 initialize(VM.getVM().getTypeDataBase()); 45 } 46 }); 47 } 48 49 private static synchronized void initialize(TypeDataBase db) { 50 Type type = db.lookupType("CodeCache"); 51 52 heapField = type.getAddressField("_heap"); 53 scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods"); 54 55 virtualConstructor = new VirtualConstructor(db); 56 // Add mappings for all possible CodeBlob subclasses 57 virtualConstructor.addMapping("BufferBlob", BufferBlob.class); 58 virtualConstructor.addMapping("nmethod", NMethod.class); 59 virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); 60 virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class); 61 virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class); 62 virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); 63 virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); 64 if (VM.getVM().isServerCompiler()) { 65 virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class); 66 virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class); 67 } 68 } 69 70 public CodeCache() { 71 heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue()); 72 } 73 74 public NMethod scavengeRootMethods() { 75 return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue()); 76 } 77 78 public boolean contains(Address p) { 79 return getHeap().contains(p); 80 } 81 82 /** When VM.getVM().isDebugging() returns true, this behaves like 83 findBlobUnsafe */ 84 public CodeBlob findBlob(Address start) { 85 CodeBlob result = findBlobUnsafe(start); 86 if (result == null) return null; 87 if (VM.getVM().isDebugging()) { 88 return result; 89 } 90 // We could potientially look up non_entrant methods 91 // NOTE: this is effectively a "guarantee", and is slightly different from the one in the VM 92 if (Assert.ASSERTS_ENABLED) { 93 Assert.that(!(result.isZombie() || result.isLockedByVM()), "unsafe access to zombie method"); 94 } 95 return result; 96 } 97 98 public CodeBlob findBlobUnsafe(Address start) { 99 CodeBlob result = null; 100 101 try { 102 result = (CodeBlob) virtualConstructor.instantiateWrapperFor(getHeap().findStart(start)); 103 } 104 catch (WrongTypeException wte) { 105 Address cbAddr = null; 106 try { 107 cbAddr = getHeap().findStart(start); 108 } 109 catch (Exception findEx) { 110 findEx.printStackTrace(); 111 } 112 113 String message = "Couldn't deduce type of CodeBlob "; 114 if (cbAddr != null) { 115 message = message + "@" + cbAddr + " "; 116 } 117 message = message + "for PC=" + start; 118 119 throw new RuntimeException(message, wte); 120 } 121 if (result == null) return null; 122 if (Assert.ASSERTS_ENABLED) { 123 // The HeapBlock that contains this blob is outside of the blob 124 // but it shouldn't be an error to find a blob based on the 125 // pointer to the HeapBlock. 126 Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)), 127 "found wrong CodeBlob"); 150 public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) { 151 try { 152 return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr); 153 } 154 catch (Exception e) { 155 String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr + 156 " (expected type nmethod, RuntimeStub, "; 157 if (VM.getVM().isClientCompiler()) { 158 message = message + " or "; 159 } 160 message = message + "SafepointBlob"; 161 if (VM.getVM().isServerCompiler()) { 162 message = message + ", DeoptimizationBlob, or ExceptionBlob"; 163 } 164 message = message + ")"; 165 throw new RuntimeException(message); 166 } 167 } 168 169 public void iterate(CodeCacheVisitor visitor) { 170 CodeHeap heap = getHeap(); 171 Address ptr = heap.begin(); 172 Address end = heap.end(); 173 174 visitor.prologue(ptr, end); 175 CodeBlob lastBlob = null; 176 while (ptr != null && ptr.lessThan(end)) { 177 try { 178 // Use findStart to get a pointer inside blob other findBlob asserts 179 CodeBlob blob = findBlobUnsafe(heap.findStart(ptr)); 180 if (blob != null) { 181 visitor.visit(blob); 182 if (blob == lastBlob) { 183 throw new InternalError("saw same blob twice"); 184 } 185 lastBlob = blob; 186 } 187 } catch (RuntimeException e) { 188 e.printStackTrace(); 189 } 190 Address next = heap.nextBlock(ptr); 191 if (next != null && next.lessThan(ptr)) { 192 throw new InternalError("pointer moved backwards"); 193 } 194 ptr = next; 195 } 196 visitor.epilogue(); 197 } 198 199 //-------------------------------------------------------------------------------- 200 // Internals only below this point 201 // 202 203 private CodeHeap getHeap() { 204 return heap; 205 } 206 } | 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.code; 26 27 import java.util.*; 28 import sun.jvm.hotspot.debugger.*; 29 import sun.jvm.hotspot.memory.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 public class CodeCache { 35 private static GrowableArray<CodeHeap> heapArray; 36 private static AddressField scavengeRootNMethodsField; 37 private static VirtualConstructor virtualConstructor; 38 39 static { 40 VM.registerVMInitializedObserver(new Observer() { 41 public void update(Observable o, Object data) { 42 initialize(VM.getVM().getTypeDataBase()); 43 } 44 }); 45 } 46 47 private static synchronized void initialize(TypeDataBase db) { 48 Type type = db.lookupType("CodeCache"); 49 50 // Get array of CodeHeaps 51 AddressField heapsField = type.getAddressField("_heaps"); 52 heapArray = GrowableArray.create(heapsField.getValue(), new StaticBaseConstructor<CodeHeap>(CodeHeap.class)); 53 54 scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods"); 55 56 virtualConstructor = new VirtualConstructor(db); 57 // Add mappings for all possible CodeBlob subclasses 58 virtualConstructor.addMapping("BufferBlob", BufferBlob.class); 59 virtualConstructor.addMapping("nmethod", NMethod.class); 60 virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class); 61 virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class); 62 virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class); 63 virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class); 64 virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); 65 if (VM.getVM().isServerCompiler()) { 66 virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class); 67 virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class); 68 } 69 } 70 71 public NMethod scavengeRootMethods() { 72 return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue()); 73 } 74 75 public boolean contains(Address p) { 76 for (int i = 0; i < heapArray.length(); ++i) { 77 if (heapArray.at(i).contains(p)) { 78 return true; 79 } 80 } 81 return false; 82 } 83 84 /** When VM.getVM().isDebugging() returns true, this behaves like 85 findBlobUnsafe */ 86 public CodeBlob findBlob(Address start) { 87 CodeBlob result = findBlobUnsafe(start); 88 if (result == null) return null; 89 if (VM.getVM().isDebugging()) { 90 return result; 91 } 92 // We could potientially look up non_entrant methods 93 // NOTE: this is effectively a "guarantee", and is slightly different from the one in the VM 94 if (Assert.ASSERTS_ENABLED) { 95 Assert.that(!(result.isZombie() || result.isLockedByVM()), "unsafe access to zombie method"); 96 } 97 return result; 98 } 99 100 public CodeBlob findBlobUnsafe(Address start) { 101 CodeBlob result = null; 102 CodeHeap containing_heap = null; 103 for (int i = 0; i < heapArray.length(); ++i) { 104 if (heapArray.at(i).contains(start)) { 105 containing_heap = heapArray.at(i); 106 break; 107 } 108 } 109 if (containing_heap == null) { 110 return null; 111 } 112 113 try { 114 result = (CodeBlob) virtualConstructor.instantiateWrapperFor(containing_heap.findStart(start)); 115 } 116 catch (WrongTypeException wte) { 117 Address cbAddr = null; 118 try { 119 cbAddr = containing_heap.findStart(start); 120 } 121 catch (Exception findEx) { 122 findEx.printStackTrace(); 123 } 124 125 String message = "Couldn't deduce type of CodeBlob "; 126 if (cbAddr != null) { 127 message = message + "@" + cbAddr + " "; 128 } 129 message = message + "for PC=" + start; 130 131 throw new RuntimeException(message, wte); 132 } 133 if (result == null) return null; 134 if (Assert.ASSERTS_ENABLED) { 135 // The HeapBlock that contains this blob is outside of the blob 136 // but it shouldn't be an error to find a blob based on the 137 // pointer to the HeapBlock. 138 Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)), 139 "found wrong CodeBlob"); 162 public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) { 163 try { 164 return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr); 165 } 166 catch (Exception e) { 167 String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr + 168 " (expected type nmethod, RuntimeStub, "; 169 if (VM.getVM().isClientCompiler()) { 170 message = message + " or "; 171 } 172 message = message + "SafepointBlob"; 173 if (VM.getVM().isServerCompiler()) { 174 message = message + ", DeoptimizationBlob, or ExceptionBlob"; 175 } 176 message = message + ")"; 177 throw new RuntimeException(message); 178 } 179 } 180 181 public void iterate(CodeCacheVisitor visitor) { 182 visitor.prologue(lowBound(), highBound()); 183 CodeBlob lastBlob = null; 184 185 for (int i = 0; i < heapArray.length(); ++i) { 186 CodeHeap current_heap = heapArray.at(i); 187 Address ptr = current_heap.begin(); 188 while (ptr != null && ptr.lessThan(current_heap.end())) { 189 try { 190 // Use findStart to get a pointer inside blob other findBlob asserts 191 CodeBlob blob = findBlobUnsafe(current_heap.findStart(ptr)); 192 if (blob != null) { 193 visitor.visit(blob); 194 if (blob == lastBlob) { 195 throw new InternalError("saw same blob twice"); 196 } 197 lastBlob = blob; 198 } 199 } catch (RuntimeException e) { 200 e.printStackTrace(); 201 } 202 Address next = current_heap.nextBlock(ptr); 203 if (next != null && next.lessThan(ptr)) { 204 throw new InternalError("pointer moved backwards"); 205 } 206 ptr = next; 207 } 208 } 209 visitor.epilogue(); 210 } 211 212 //-------------------------------------------------------------------------------- 213 // Internals only below this point 214 // 215 216 private Address lowBound() { 217 Address low = heapArray.at(0).begin(); 218 for (int i = 1; i < heapArray.length(); ++i) { 219 if (heapArray.at(i).begin().lessThan(low)) { 220 low = heapArray.at(i).begin(); 221 } 222 } 223 return low; 224 } 225 226 private Address highBound() { 227 Address high = heapArray.at(0).end(); 228 for (int i = 1; i < heapArray.length(); ++i) { 229 if (heapArray.at(i).end().greaterThan(high)) { 230 high = heapArray.at(i).end(); 231 } 232 } 233 return high; 234 } 235 } |