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.compiler; 26 27 import java.util.*; 28 29 import sun.jvm.hotspot.code.*; 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.runtime.*; 32 import sun.jvm.hotspot.types.*; 33 import sun.jvm.hotspot.utilities.*; 34 35 public class OopMapSet extends VMObject { 36 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null; 37 38 private static CIntegerField omCountField; 39 private static CIntegerField omSizeField; 40 private static AddressField omDataField; 41 private static int REG_COUNT; 42 private static int SAVED_ON_ENTRY_REG_COUNT; 43 private static int C_SAVED_ON_ENTRY_REG_COUNT; 44 private static class MyVisitor implements OopMapVisitor { 45 private AddressVisitor addressVisitor; 46 47 public MyVisitor(AddressVisitor oopVisitor) { 48 setAddressVisitor(oopVisitor); 49 } 50 51 public void setAddressVisitor(AddressVisitor addressVisitor) { 52 this.addressVisitor = addressVisitor; 53 } 54 55 public void visitOopLocation(Address oopAddr) { 56 addressVisitor.visitAddress(oopAddr); 57 } 58 59 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { 60 if (VM.getVM().isClientCompiler()) { 61 Assert.that(false, "should not reach here"); 62 } else if (VM.getVM().isServerCompiler() && 63 VM.getVM().useDerivedPointerTable()) { 65 } 66 } 67 68 public void visitValueLocation(Address valueAddr) { 69 } 70 71 public void visitNarrowOopLocation(Address narrowOopAddr) { 72 addressVisitor.visitCompOopAddress(narrowOopAddr); 73 } 74 } 75 76 static { 77 VM.registerVMInitializedObserver(new Observer() { 78 public void update(Observable o, Object data) { 79 initialize(VM.getVM().getTypeDataBase()); 80 } 81 }); 82 } 83 84 private static void initialize(TypeDataBase db) { 85 Type type = db.lookupType("OopMapSet"); 86 87 omCountField = type.getCIntegerField("_om_count"); 88 omSizeField = type.getCIntegerField("_om_size"); 89 omDataField = type.getAddressField("_om_data"); 90 91 if (!VM.getVM().isCore()) { 92 REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue(); 93 if (VM.getVM().isServerCompiler()) { 94 SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue(); 95 C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue(); 96 } 97 } 98 } 99 100 public OopMapSet(Address addr) { 101 super(addr); 102 } 103 104 /** Returns the number of OopMaps in this OopMapSet */ 105 public long getSize() { 106 return omCountField.getValue(addr); 107 } 108 109 /** returns the OopMap at a given index */ 110 public OopMap getMapAt(int index) { 111 if (Assert.ASSERTS_ENABLED) { 112 Assert.that((index >= 0) && (index <= getSize()),"bad index"); 113 } 114 Address omDataAddr = omDataField.getValue(addr); 115 Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize()); 116 if (oopMapAddr == null) { 117 return null; 118 } 119 return new OopMap(oopMapAddr); 120 } 121 122 public OopMap findMapAtOffset(long pcOffset, boolean debugging) { 123 int i; 124 int len = (int) getSize(); 125 if (Assert.ASSERTS_ENABLED) { 126 Assert.that(len > 0, "must have pointer maps"); 127 } 128 129 // Scan through oopmaps. Stop when current offset is either equal or greater 130 // than the one we are looking for. 131 for (i = 0; i < len; i++) { 132 if (getMapAt(i).getOffset() >= pcOffset) { 133 break; 134 } 135 } 136 137 if (!debugging) { 138 if (Assert.ASSERTS_ENABLED) { 139 Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len); 140 Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found"); 141 } 142 } else { 143 if (i == len) { 144 if (DEBUG) { 145 System.out.println("can't find oopmap at " + pcOffset); 146 System.out.print("Oopmap offsets are [ "); 147 for (i = 0; i < len; i++) { 148 System.out.print(getMapAt(i).getOffset()); 149 } 150 System.out.println("]"); 151 } 152 i = len - 1; 153 return getMapAt(i); 154 } 155 } 156 157 OopMap m = getMapAt(i); 158 return m; 159 } 160 161 /** Visitation -- iterates through the frame for a compiled method. 162 This is a very generic mechanism that requires the Address to be 163 dereferenced by the callee. Other, more specialized, visitation 164 mechanisms are given below. */ 165 public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) { 166 allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging); 167 } 168 169 /** Note that there are 4 required AddressVisitors: one for oops, 170 one for derived oops, one for values, and one for dead values */ 171 public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) { 172 if (Assert.ASSERTS_ENABLED) { 173 CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC()); 174 Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in"); 175 } 176 177 OopMapSet maps = cb.getOopMaps(); 178 OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); 179 if (Assert.ASSERTS_ENABLED) { 180 Assert.that(map != null, "no ptr map found"); 181 } 182 183 // handle derived pointers first (otherwise base pointer may be 184 // changed before derived pointer offset has been collected) 185 OopMapValue omv; 186 { 187 for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) { 188 if (VM.getVM().isClientCompiler()) { 189 Assert.that(false, "should not reach here"); 190 } 191 omv = oms.getCurrent(); 192 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); 193 if (loc != null) { 194 Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap); 195 Address derivedLoc = loc; 196 visitor.visitDerivedOopLocation(baseLoc, derivedLoc); 197 } 198 } 199 } 200 201 // We want narow oop, value and oop oop_types 202 OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] { 203 OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE 204 }; 205 206 { 207 for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) { 208 omv = oms.getCurrent(); 209 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); 210 if (loc != null) { 211 if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) { 212 // This assert commented out because this will be useful 213 // to detect in the debugging system 214 // assert(Universe::is_heap_or_null(*loc), "found non oop pointer"); 215 visitor.visitOopLocation(loc); 216 } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { 217 visitor.visitValueLocation(loc); 218 } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) { 219 visitor.visitNarrowOopLocation(loc); 220 } 221 } 222 } 223 } 224 } 225 226 /** Update callee-saved register info for the following frame. 227 Should only be called in non-core builds. */ 228 public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) { 229 if (Assert.ASSERTS_ENABLED) { 230 Assert.that(!VM.getVM().isCore(), "non-core builds only"); 231 } 232 233 if (!VM.getVM().isDebugging()) { 234 if (Assert.ASSERTS_ENABLED) { 235 OopMapSet maps = cb.getOopMaps(); 236 Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob"); 237 } 238 } else { 239 // Hack for some topmost frames that have been found with empty 240 // OopMapSets. (Actually have not seen the null case, but don't 241 // want to take any chances.) See HSDB.showThreadStackMemory(). 242 OopMapSet maps = cb.getOopMaps(); 243 if ((maps == null) || (maps.getSize() == 0)) { 244 return; 245 } 246 } 247 248 // Check if caller must update oop argument 249 regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); 250 251 int nofCallee = 0; 252 Address[] locs = new Address[2 * REG_COUNT + 1]; 253 VMReg [] regs = new VMReg [2 * REG_COUNT + 1]; 254 // ("+1" because REG_COUNT might be zero) 255 256 // Scan through oopmap and find location of all callee-saved registers 257 // (we do not do update in place, since info could be overwritten) 258 OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); 259 if (Assert.ASSERTS_ENABLED) { 260 Assert.that(map != null, "no ptr map found"); 261 } 262 263 OopMapValue omv = null; 264 for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) { 265 omv = oms.getCurrent(); 266 if (Assert.ASSERTS_ENABLED) { 267 Assert.that(nofCallee < 2 * REG_COUNT, "overflow"); 268 } 269 regs[nofCallee] = omv.getContentReg(); 270 locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap); 271 nofCallee++; 272 } 273 274 // Check that runtime stubs save all callee-saved registers 275 // After adapter frames were deleted C2 doesn't use callee save registers at present 276 if (Assert.ASSERTS_ENABLED) { 277 if (VM.getVM().isServerCompiler()) { 278 Assert.that(!cb.isRuntimeStub() || 279 (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT), 280 "must save all"); 281 } 282 } 283 284 // Copy found callee-saved register to reg_map 285 for (int i = 0; i < nofCallee; i++) { 286 regMap.setLocation(regs[i], locs[i]); 287 } 288 } 289 } | 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.compiler; 26 27 import java.util.*; 28 29 import sun.jvm.hotspot.code.*; 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.runtime.*; 32 import sun.jvm.hotspot.types.*; 33 import sun.jvm.hotspot.utilities.*; 34 35 public class ImmutableOopMapSet extends VMObject { 36 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null; 37 38 private static CIntegerField countField; 39 private static CIntegerField sizeField; 40 private static AddressField omDataField; 41 private static int REG_COUNT; 42 private static int SAVED_ON_ENTRY_REG_COUNT; 43 private static int C_SAVED_ON_ENTRY_REG_COUNT; 44 private static long classSize; 45 46 private static class MyVisitor implements OopMapVisitor { 47 private AddressVisitor addressVisitor; 48 49 public MyVisitor(AddressVisitor oopVisitor) { 50 setAddressVisitor(oopVisitor); 51 } 52 53 public void setAddressVisitor(AddressVisitor addressVisitor) { 54 this.addressVisitor = addressVisitor; 55 } 56 57 public void visitOopLocation(Address oopAddr) { 58 addressVisitor.visitAddress(oopAddr); 59 } 60 61 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { 62 if (VM.getVM().isClientCompiler()) { 63 Assert.that(false, "should not reach here"); 64 } else if (VM.getVM().isServerCompiler() && 65 VM.getVM().useDerivedPointerTable()) { 67 } 68 } 69 70 public void visitValueLocation(Address valueAddr) { 71 } 72 73 public void visitNarrowOopLocation(Address narrowOopAddr) { 74 addressVisitor.visitCompOopAddress(narrowOopAddr); 75 } 76 } 77 78 static { 79 VM.registerVMInitializedObserver(new Observer() { 80 public void update(Observable o, Object data) { 81 initialize(VM.getVM().getTypeDataBase()); 82 } 83 }); 84 } 85 86 private static void initialize(TypeDataBase db) { 87 Type type = db.lookupType("ImmutableOopMapSet"); 88 89 countField = type.getCIntegerField("_count"); 90 sizeField = type.getCIntegerField("_size"); 91 classSize = type.getSize(); 92 93 if (!VM.getVM().isCore()) { 94 REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue(); 95 if (VM.getVM().isServerCompiler()) { 96 SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue(); 97 C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue(); 98 } 99 } 100 } 101 102 public ImmutableOopMapSet(Address addr) { 103 super(addr); 104 } 105 106 /** 107 * Returns the number of OopMaps in this ImmutableOopMapSet 108 */ 109 public long getSize() { 110 return countField.getValue(addr); 111 } 112 113 public int getCount() { return (int) countField.getValue(addr); } 114 115 private Address dataStart() { 116 return (addr.addOffsetTo(ImmutableOopMapSet.classSize * getCount())); 117 } 118 119 public ImmutableOopMapPair pairAt(int index) { 120 Assert.that((index >= 0) && (index < getCount()), "bad index"); 121 return new ImmutableOopMapPair(addr.addOffsetTo(index * ImmutableOopMapPair.classSize())); 122 } 123 124 /** 125 * returns the OopMap at a given index 126 */ 127 public ImmutableOopMap getMapAt(int index) { 128 if (Assert.ASSERTS_ENABLED) { 129 Assert.that((index >= 0) && (index <= getSize()), "bad index"); 130 } 131 132 ImmutableOopMapPair immutableOopMapPair = pairAt(index); 133 return getMap(immutableOopMapPair); 134 } 135 136 public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) { 137 int i; 138 int len = (int) getSize(); 139 if (Assert.ASSERTS_ENABLED) { 140 Assert.that(len > 0, "must have pointer maps"); 141 } 142 143 // Scan through oopmaps. Stop when current offset is either equal or greater 144 // than the one we are looking for. 145 for (i = 0; i < len; i++) { 146 if (pairAt(i).getPC() >= pcOffset) { 147 break; 148 } 149 } 150 151 if (!debugging) { 152 if (Assert.ASSERTS_ENABLED) { 153 Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len); 154 Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found"); 155 } 156 } else { 157 if (i == len) { 158 if (DEBUG) { 159 System.out.println("can't find oopmap at " + pcOffset); 160 System.out.print("Oopmap offsets are [ "); 161 for (i = 0; i < len; i++) { 162 System.out.print(pairAt(i).getPC()); 163 } 164 System.out.println("]"); 165 } 166 i = len - 1; 167 return getMapAt(i); 168 } 169 } 170 171 ImmutableOopMap m = getMapAt(i); 172 return m; 173 } 174 175 /** 176 * Visitation -- iterates through the frame for a compiled method. 177 * This is a very generic mechanism that requires the Address to be 178 * dereferenced by the callee. Other, more specialized, visitation 179 * mechanisms are given below. 180 */ 181 public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) { 182 allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging); 183 } 184 185 /** 186 * Note that there are 4 required AddressVisitors: one for oops, 187 * one for derived oops, one for values, and one for dead values 188 */ 189 public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) { 190 if (Assert.ASSERTS_ENABLED) { 191 CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC()); 192 Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in"); 193 } 194 195 ImmutableOopMapSet maps = cb.getOopMaps(); 196 ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); 197 if (Assert.ASSERTS_ENABLED) { 198 Assert.that(map != null, "no ptr map found"); 199 } 200 201 // handle derived pointers first (otherwise base pointer may be 202 // changed before derived pointer offset has been collected) 203 OopMapValue omv; 204 { 205 for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); !oms.isDone(); oms.next()) { 206 if (VM.getVM().isClientCompiler()) { 207 Assert.that(false, "should not reach here"); 208 } 209 omv = oms.getCurrent(); 210 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); 211 if (loc != null) { 212 Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap); 213 Address derivedLoc = loc; 214 visitor.visitDerivedOopLocation(baseLoc, derivedLoc); 215 } 216 } 217 } 218 219 // We want narow oop, value and oop oop_types 220 OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[]{ 221 OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE 222 }; 223 224 { 225 for (OopMapStream oms = new OopMapStream(map, values); !oms.isDone(); oms.next()) { 226 omv = oms.getCurrent(); 227 Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap); 228 if (loc != null) { 229 if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) { 230 // This assert commented out because this will be useful 231 // to detect in the debugging system 232 // assert(Universe::is_heap_or_null(*loc), "found non oop pointer"); 233 visitor.visitOopLocation(loc); 234 } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { 235 visitor.visitValueLocation(loc); 236 } else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) { 237 visitor.visitNarrowOopLocation(loc); 238 } 239 } 240 } 241 } 242 } 243 244 /** 245 * Update callee-saved register info for the following frame. 246 * Should only be called in non-core builds. 247 */ 248 public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) { 249 if (Assert.ASSERTS_ENABLED) { 250 Assert.that(!VM.getVM().isCore(), "non-core builds only"); 251 } 252 253 if (!VM.getVM().isDebugging()) { 254 if (Assert.ASSERTS_ENABLED) { 255 ImmutableOopMapSet maps = cb.getOopMaps(); 256 Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty ImmutableOopMapSet for CodeBlob"); 257 } 258 } else { 259 // Hack for some topmost frames that have been found with empty 260 // OopMapSets. (Actually have not seen the null case, but don't 261 // want to take any chances.) See HSDB.showThreadStackMemory(). 262 ImmutableOopMapSet maps = cb.getOopMaps(); 263 if ((maps == null) || (maps.getSize() == 0)) { 264 return; 265 } 266 } 267 268 // Check if caller must update oop argument 269 regMap.setIncludeArgumentOops(cb.callerMustGCArguments()); 270 271 int nofCallee = 0; 272 Address[] locs = new Address[2 * REG_COUNT + 1]; 273 VMReg[] regs = new VMReg[2 * REG_COUNT + 1]; 274 // ("+1" because REG_COUNT might be zero) 275 276 // Scan through oopmap and find location of all callee-saved registers 277 // (we do not do update in place, since info could be overwritten) 278 ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging); 279 if (Assert.ASSERTS_ENABLED) { 280 Assert.that(map != null, "no ptr map found"); 281 } 282 283 OopMapValue omv = null; 284 for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) { 285 omv = oms.getCurrent(); 286 if (Assert.ASSERTS_ENABLED) { 287 Assert.that(nofCallee < 2 * REG_COUNT, "overflow"); 288 } 289 regs[nofCallee] = omv.getContentReg(); 290 locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap); 291 nofCallee++; 292 } 293 294 // Check that runtime stubs save all callee-saved registers 295 // After adapter frames were deleted C2 doesn't use callee save registers at present 296 if (Assert.ASSERTS_ENABLED) { 297 if (VM.getVM().isServerCompiler()) { 298 Assert.that(!cb.isRuntimeStub() || 299 (nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT), 300 "must save all"); 301 } 302 } 303 304 // Copy found callee-saved register to reg_map 305 for (int i = 0; i < nofCallee; i++) { 306 regMap.setLocation(regs[i], locs[i]); 307 } 308 } 309 310 public ImmutableOopMapPair getPairAt(int index) { 311 return pairAt(index); 312 } 313 314 public ImmutableOopMap getMap(ImmutableOopMapPair pair) { 315 Assert.that(pair.getOffset() < (int) sizeField.getValue(), "boundary check"); 316 return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset())); 317 } 318 } |