diff agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 148e5441d916
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package sun.jvm.hotspot.code;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.memory.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class CodeCache {
+  private static AddressField       heapField;
+  private static VirtualConstructor virtualConstructor;
+
+  private CodeHeap heap;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static synchronized void initialize(TypeDataBase db) {
+    Type type = db.lookupType("CodeCache");
+
+    heapField = type.getAddressField("_heap");
+
+    virtualConstructor = new VirtualConstructor(db);
+    // Add mappings for all possible CodeBlob subclasses
+    virtualConstructor.addMapping("BufferBlob", BufferBlob.class);
+    virtualConstructor.addMapping("nmethod", NMethod.class);
+    virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);
+    virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
+    virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
+    if (VM.getVM().isServerCompiler()) {
+      virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class);
+      virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class);
+    }
+  }
+
+  public CodeCache() {
+    heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue());
+  }
+
+  public boolean contains(Address p) {
+    return getHeap().contains(p);
+  }
+
+  /** When VM.getVM().isDebugging() returns true, this behaves like
+      findBlobUnsafe */
+  public CodeBlob findBlob(Address start) {
+    CodeBlob result = findBlobUnsafe(start);
+    if (result == null) return null;
+    if (VM.getVM().isDebugging()) {
+      return result;
+    }
+    // We could potientially look up non_entrant methods
+    // NOTE: this is effectively a "guarantee", and is slightly different from the one in the VM
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!(result.isZombie() || result.isLockedByVM()), "unsafe access to zombie method");
+    }
+    return result;
+  }
+
+  public CodeBlob findBlobUnsafe(Address start) {
+    CodeBlob result = null;
+
+    try {
+      result = (CodeBlob) virtualConstructor.instantiateWrapperFor(getHeap().findStart(start));
+    }
+    catch (WrongTypeException wte) {
+      Address cbAddr = null;
+      try {
+        cbAddr = getHeap().findStart(start);
+      }
+      catch (Exception findEx) {
+        findEx.printStackTrace();
+      }
+
+      String message = "Couldn't deduce type of CodeBlob ";
+      if (cbAddr != null) {
+        message = message + "@" + cbAddr + " ";
+      }
+      message = message + "for PC=" + start;
+
+      throw new RuntimeException(message, wte);
+    }
+    if (result == null) return null;
+    if (Assert.ASSERTS_ENABLED) {
+      // The HeapBlock that contains this blob is outside of the blob
+      // but it shouldn't be an error to find a blob based on the
+      // pointer to the HeapBlock.
+      Assert.that(result.blobContains(start) || result.blobContains(start.addOffsetTo(8)),
+                                                                    "found wrong CodeBlob");
+    }
+    return result;
+  }
+
+  public NMethod findNMethod(Address start) {
+    CodeBlob cb = findBlob(start);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");
+    }
+    return (NMethod) cb;
+  }
+
+  public NMethod findNMethodUnsafe(Address start) {
+    CodeBlob cb = findBlobUnsafe(start);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");
+    }
+    return (NMethod) cb;
+  }
+
+  /** Routine for instantiating appropriately-typed wrapper for a
+      CodeBlob. Used by CodeCache, Runtime1, etc. */
+  public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) {
+    try {
+      return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr);
+    }
+    catch (Exception e) {
+      String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr +
+                       " (expected type nmethod, RuntimeStub, ";
+      if (VM.getVM().isClientCompiler()) {
+        message = message + " or ";
+      }
+      message = message + "SafepointBlob";
+      if (VM.getVM().isServerCompiler()) {
+        message = message + ", DeoptimizationBlob, or ExceptionBlob";
+      }
+      message = message + ")";
+      throw new RuntimeException(message);
+    }
+  }
+
+  public void iterate(CodeCacheVisitor visitor) {
+    CodeHeap heap = getHeap();
+    Address ptr = heap.begin();
+    Address end = heap.end();
+
+    visitor.prologue(ptr, end);
+    CodeBlob lastBlob = null;
+    while (ptr != null && ptr.lessThan(end)) {
+      try {
+        CodeBlob blob = findBlobUnsafe(ptr);
+        if (blob != null) {
+          visitor.visit(blob);
+          if (blob == lastBlob) {
+            throw new InternalError("saw same blob twice");
+          }
+          lastBlob = blob;
+        }
+      } catch (RuntimeException e) {
+        e.printStackTrace();
+      }
+      Address next = heap.nextBlock(ptr);
+      if (next != null && next.lessThan(ptr)) {
+        throw new InternalError("pointer moved backwards");
+      }
+      ptr = next;
+    }
+    visitor.epilogue();
+  }
+
+  //--------------------------------------------------------------------------------
+  // Internals only below this point
+  //
+
+  private CodeHeap getHeap() {
+    return heap;
+  }
+}