1 /* 2 * Copyright 2000-2005 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.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("SafepointBlob", SafepointBlob.class); 61 virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class); 62 if (VM.getVM().isServerCompiler()) { 63 virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class); 64 virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class); 65 } 66 } 67 68 public CodeCache() { 69 heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue()); 70 } 71 72 public NMethod scavengeRootMethods() { 73 return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue()); 74 } 75 76 public boolean contains(Address p) { 77 return getHeap().contains(p); 78 } 79 80 /** When VM.getVM().isDebugging() returns true, this behaves like 81 findBlobUnsafe */ 82 public CodeBlob findBlob(Address start) { 83 CodeBlob result = findBlobUnsafe(start); 84 if (result == null) return null; 85 if (VM.getVM().isDebugging()) { 86 return result; 87 } 88 // We could potientially look up non_entrant methods 89 // NOTE: this is effectively a "guarantee", and is slightly different from the one in the VM 90 if (Assert.ASSERTS_ENABLED) { 91 Assert.that(!(result.isZombie() || result.isLockedByVM()), "unsafe access to zombie method"); 92 } 93 return result; 94 } 95 96 public CodeBlob findBlobUnsafe(Address start) { 97 CodeBlob result = null; 98 99 try { 100 result = (CodeBlob) virtualConstructor.instantiateWrapperFor(getHeap().findStart(start)); 101 } 102 catch (WrongTypeException wte) { 103 Address cbAddr = null; 104 try { 105 cbAddr = getHeap().findStart(start); 106 } 107 catch (Exception findEx) { 108 findEx.printStackTrace(); 109 } 110 111 String message = "Couldn't deduce type of CodeBlob "; 112 if (cbAddr != null) { 113 message = message + "@" + cbAddr + " "; 114 } 115 message = message + "for PC=" + start; 116 117 throw new RuntimeException(message, wte); 118 } 119 if (result == null) return null; 120 if (Assert.ASSERTS_ENABLED) { 121 // The HeapBlock that contains this blob is outside of the blob 122 // but it shouldn't be an error to find a blob based on the 123 // pointer to the HeapBlock. 124 Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)), 125 "found wrong CodeBlob"); 126 } 127 return result; 128 } 129 130 public NMethod findNMethod(Address start) { 131 CodeBlob cb = findBlob(start); 132 if (Assert.ASSERTS_ENABLED) { 133 Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod"); 134 } 135 return (NMethod) cb; 136 } 137 138 public NMethod findNMethodUnsafe(Address start) { 139 CodeBlob cb = findBlobUnsafe(start); 140 if (Assert.ASSERTS_ENABLED) { 141 Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod"); 142 } 143 return (NMethod) cb; 144 } 145 146 /** Routine for instantiating appropriately-typed wrapper for a 147 CodeBlob. Used by CodeCache, Runtime1, etc. */ 148 public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) { 149 try { 150 return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr); 151 } 152 catch (Exception e) { 153 String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr + 154 " (expected type nmethod, RuntimeStub, "; 155 if (VM.getVM().isClientCompiler()) { 156 message = message + " or "; 157 } 158 message = message + "SafepointBlob"; 159 if (VM.getVM().isServerCompiler()) { 160 message = message + ", DeoptimizationBlob, or ExceptionBlob"; 161 } 162 message = message + ")"; 163 throw new RuntimeException(message); 164 } 165 } 166 167 public void iterate(CodeCacheVisitor visitor) { 168 CodeHeap heap = getHeap(); 169 Address ptr = heap.begin(); 170 Address end = heap.end(); 171 172 visitor.prologue(ptr, end); 173 CodeBlob lastBlob = null; 174 while (ptr != null && ptr.lessThan(end)) { 175 try { 176 // Use findStart to get a pointer inside blob other findBlob asserts 177 CodeBlob blob = findBlobUnsafe(heap.findStart(ptr)); 178 if (blob != null) { 179 visitor.visit(blob); 180 if (blob == lastBlob) { 181 throw new InternalError("saw same blob twice"); 182 } 183 lastBlob = blob; 184 } 185 } catch (RuntimeException e) { 186 e.printStackTrace(); 187 } 188 Address next = heap.nextBlock(ptr); 189 if (next != null && next.lessThan(ptr)) { 190 throw new InternalError("pointer moved backwards"); 191 } 192 ptr = next; 193 } 194 visitor.epilogue(); 195 } 196 197 //-------------------------------------------------------------------------------- 198 // Internals only below this point 199 // 200 201 private CodeHeap getHeap() { 202 return heap; 203 } 204 }