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

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,288 @@
+/*
+ * 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.compiler;
+
+import java.util.*;
+
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.utilities.*;
+
+public class OopMapSet extends VMObject {
+  private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null;
+
+  private static CIntegerField omCountField;
+  private static CIntegerField omSizeField;
+  private static AddressField  omDataField;
+  private static int REG_COUNT;
+  private static int SAVED_ON_ENTRY_REG_COUNT;
+  private static int C_SAVED_ON_ENTRY_REG_COUNT;
+  private static class MyVisitor implements OopMapVisitor {
+    private AddressVisitor addressVisitor;
+
+    public MyVisitor(AddressVisitor oopVisitor) {
+      setAddressVisitor(oopVisitor);
+    }
+
+    public void setAddressVisitor(AddressVisitor addressVisitor) {
+      this.addressVisitor = addressVisitor;
+    }
+
+    public void visitOopLocation(Address oopAddr) {
+      addressVisitor.visitAddress(oopAddr);
+    }
+
+    public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
+      if (VM.getVM().isClientCompiler()) {
+        Assert.that(false, "should not reach here");
+      } else if (VM.getVM().isServerCompiler() &&
+                 VM.getVM().useDerivedPointerTable()) {
+        Assert.that(false, "FIXME: add derived pointer table");
+      }
+    }
+
+    public void visitValueLocation(Address valueAddr) {
+    }
+
+    public void visitDeadLocation(Address deadAddr) {
+    }
+  }
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("OopMapSet");
+
+    omCountField  = type.getCIntegerField("_om_count");
+    omSizeField   = type.getCIntegerField("_om_size");
+    omDataField   = type.getAddressField("_om_data");
+
+    if (!VM.getVM().isCore()) {
+      REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
+      if (VM.getVM().isServerCompiler()) {
+        SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();
+        C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();
+      }
+    }
+  }
+
+  public OopMapSet(Address addr) {
+    super(addr);
+  }
+
+  /** Returns the number of OopMaps in this OopMapSet */
+  public long getSize() {
+    return omCountField.getValue(addr);
+  }
+
+  /** returns the OopMap at a given index */
+  public OopMap getMapAt(int index) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that((index >= 0) && (index <= getSize()),"bad index");
+    }
+    Address omDataAddr = omDataField.getValue(addr);
+    Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize());
+    if (oopMapAddr == null) {
+      return null;
+    }
+    return new OopMap(oopMapAddr);
+  }
+
+  public OopMap findMapAtOffset(long pcOffset, boolean debugging) {
+    int i;
+    int len = (int) getSize();
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(len > 0, "must have pointer maps");
+    }
+
+    // Scan through oopmaps. Stop when current offset is either equal or greater
+    // than the one we are looking for.
+    for (i = 0; i < len; i++) {
+      if (getMapAt(i).getOffset() >= pcOffset) {
+        break;
+      }
+    }
+
+    if (!debugging) {
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
+        Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found");
+      }
+    } else {
+      if (i == len) {
+        if (DEBUG) {
+          System.out.println("can't find oopmap at " + pcOffset);
+          System.out.print("Oopmap offsets are [ ");
+          for (i = 0; i < len; i++) {
+            System.out.print(getMapAt(i).getOffset());
+          }
+          System.out.println("]");
+        }
+        i = len - 1;
+        return getMapAt(i);
+      }
+    }
+
+    OopMap m = getMapAt(i);
+    return m;
+  }
+
+  /** Visitation -- iterates through the frame for a compiled method.
+      This is a very generic mechanism that requires the Address to be
+      dereferenced by the callee. Other, more specialized, visitation
+      mechanisms are given below. */
+  public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
+    allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
+  }
+
+  /** Note that there are 4 required AddressVisitors: one for oops,
+      one for derived oops, one for values, and one for dead values */
+  public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
+    if (Assert.ASSERTS_ENABLED) {
+      CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
+      Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
+    }
+
+    OopMapSet maps = cb.getOopMaps();
+    OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "no ptr map found");
+    }
+
+    // handle derived pointers first (otherwise base pointer may be
+    // changed before derived pointer offset has been collected)
+    OopMapValue omv;
+    {
+      for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) {
+        if (VM.getVM().isClientCompiler()) {
+          Assert.that(false, "should not reach here");
+        }
+        omv = oms.getCurrent();
+        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
+        if (loc != null) {
+          Address baseLoc    = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
+          Address derivedLoc = loc;
+          visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
+        }
+      }
+    }
+
+    // We want dead, value and oop oop_types
+    OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
+      OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.DEAD_VALUE
+    };
+
+    {
+      for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) {
+        omv = oms.getCurrent();
+        Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
+        if (loc != null) {
+          if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {
+            // This assert commented out because this will be useful
+            // to detect in the debugging system
+            // assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
+            visitor.visitOopLocation(loc);
+          } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
+            visitor.visitValueLocation(loc);
+          } else if (omv.getType() == OopMapValue.OopTypes.DEAD_VALUE) {
+            visitor.visitDeadLocation(loc);
+          }
+        }
+      }
+    }
+  }
+
+  /** Update callee-saved register info for the following frame.
+      Should only be called in non-core builds. */
+  public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(!VM.getVM().isCore(), "non-core builds only");
+    }
+
+    if (!VM.getVM().isDebugging()) {
+      if (Assert.ASSERTS_ENABLED) {
+        OopMapSet maps = cb.getOopMaps();
+        Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob");
+      }
+    } else {
+      // Hack for some topmost frames that have been found with empty
+      // OopMapSets. (Actually have not seen the null case, but don't
+      // want to take any chances.) See HSDB.showThreadStackMemory().
+      OopMapSet maps = cb.getOopMaps();
+      if ((maps == null) || (maps.getSize() == 0)) {
+        return;
+      }
+    }
+
+    // Check if caller must update oop argument
+    regMap.setIncludeArgumentOops(cb.callerMustGCArguments(regMap.getThread()));
+
+    int nofCallee = 0;
+    Address[] locs = new Address[2 * REG_COUNT + 1];
+    VMReg  [] regs = new VMReg  [2 * REG_COUNT + 1];
+    // ("+1" because REG_COUNT might be zero)
+
+    // Scan through oopmap and find location of all callee-saved registers
+    // (we do not do update in place, since info could be overwritten)
+    OopMap map  = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(map != null, "no ptr map found");
+    }
+
+    OopMapValue omv = null;
+    for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
+      omv = oms.getCurrent();
+      if (Assert.ASSERTS_ENABLED) {
+        Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
+      }
+      regs[nofCallee] = omv.getContentReg();
+      locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);
+      nofCallee++;
+    }
+
+    // Check that runtime stubs save all callee-saved registers
+    // After adapter frames were deleted C2 doesn't use callee save registers at present
+    if (Assert.ASSERTS_ENABLED) {
+      if (VM.getVM().isServerCompiler()) {
+        Assert.that(!cb.isRuntimeStub() ||
+                    (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
+                    "must save all");
+      }
+    }
+
+    // Copy found callee-saved register to reg_map
+    for (int i = 0; i < nofCallee; i++) {
+      regMap.setLocation(regs[i], locs[i]);
+    }
+  }
+}