1 /* 2 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. 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 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.oops; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 // A MethodData provides interpreter profiling information 35 36 public class MethodData extends Oop { 37 static { 38 VM.registerVMInitializedObserver(new Observer() { 39 public void update(Observable o, Object data) { 40 initialize(VM.getVM().getTypeDataBase()); 41 } 42 }); 43 } 44 45 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 46 Type type = db.lookupType("methodDataOopDesc"); 47 baseOffset = type.getSize(); 48 49 size = new CIntField(type.getCIntegerField("_size"), 0); 50 method = new OopField(type.getOopField("_method"), 0); 51 // FIXME: add more fields and accessors 52 } 53 54 MethodData(OopHandle handle, ObjectHeap heap) { 55 super(handle, heap); 56 } 57 58 public boolean isMethodData() { return true; } 59 60 private static long baseOffset; 61 private static CIntField size; 62 private static OopField method; 63 64 public long getObjectSize() { 65 return alignObjectSize(size.getValue(this)); 66 } 67 68 public Method getMethod() { 69 return (Method) method.getValue(this); 70 } 71 72 public void printValueOn(PrintStream tty) { 73 Method m = getMethod(); 74 tty.print("MethodData for " + m.getName().asString() + m.getSignature().asString()); 75 } 76 77 public void iterateFields(OopVisitor visitor, boolean doVMFields) { 78 super.iterateFields(visitor, doVMFields); 79 if (doVMFields) { 80 visitor.doOop(method, true); 81 visitor.doCInt(size, true); 82 } 83 } 84 } | 1 /* 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. 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 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.oops; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.runtime.*; 31 import sun.jvm.hotspot.types.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 // A MethodData provides interpreter profiling information 35 36 public class MethodData extends Oop { 37 static int TypeProfileWidth = 2; 38 static int BciProfileWidth = 2; 39 static int CompileThreshold; 40 41 static int Reason_many; // indicates presence of several reasons 42 static int Reason_none; // indicates absence of a relevant deopt. 43 static int Reason_LIMIT; 44 static int Reason_RECORDED_LIMIT; // some are not recorded per bc 45 46 private static String[] trapReasonName; 47 48 static String trapReasonName(int reason) { 49 if (reason == Reason_many) return "many"; 50 if (reason < Reason_LIMIT) 51 return trapReasonName[reason]; 52 return "reason" + reason; 53 } 54 55 56 static int trapStateReason(int trapState) { 57 // This assert provides the link between the width of DataLayout.trapBits 58 // and the encoding of "recorded" reasons. It ensures there are enough 59 // bits to store all needed reasons in the per-BCI MDO profile. 60 // assert(dsReasonMask >= reasonRecordedLimit, "enough bits"); 61 int recompileBit = (trapState & dsRecompileBit); 62 trapState -= recompileBit; 63 if (trapState == dsReasonMask) { 64 return Reason_many; 65 } else { 66 // assert((int)reasonNone == 0, "state=0 => Reason_none"); 67 return trapState; 68 } 69 } 70 71 72 static final int dsReasonMask = DataLayout.trapMask >> 1; 73 static final int dsRecompileBit = DataLayout.trapMask - dsReasonMask; 74 75 static boolean trapStateIsRecompiled(int trapState) { 76 return (trapState & dsRecompileBit) != 0; 77 } 78 79 static boolean reasonIsRecordedPerBytecode(int reason) { 80 return reason > Reason_none && reason < Reason_RECORDED_LIMIT; 81 } 82 static int trapStateAddReason(int trapState, int reason) { 83 // assert(reasonIsRecordedPerBytecode((DeoptReason)reason) || reason == reasonMany, "valid reason"); 84 int recompileBit = (trapState & dsRecompileBit); 85 trapState -= recompileBit; 86 if (trapState == dsReasonMask) { 87 return trapState + recompileBit; // already at state lattice bottom 88 } else if (trapState == reason) { 89 return trapState + recompileBit; // the condition is already true 90 } else if (trapState == 0) { 91 return reason + recompileBit; // no condition has yet been true 92 } else { 93 return dsReasonMask + recompileBit; // fall to state lattice bottom 94 } 95 } 96 static int trapStateSetRecompiled(int trapState, boolean z) { 97 if (z) return trapState | dsRecompileBit; 98 else return trapState & ~dsRecompileBit; 99 } 100 101 static String formatTrapState(int trapState) { 102 int reason = trapStateReason(trapState); 103 boolean recompFlag = trapStateIsRecompiled(trapState); 104 // Re-encode the state from its decoded components. 105 int decodedState = 0; 106 if (reasonIsRecordedPerBytecode(reason) || reason == Reason_many) 107 decodedState = trapStateAddReason(decodedState, reason); 108 if (recompFlag) 109 decodedState = trapStateSetRecompiled(decodedState, recompFlag); 110 // If the state re-encodes properly, format it symbolically. 111 // Because this routine is used for debugging and diagnostics, 112 // be robust even if the state is a strange value. 113 if (decodedState != trapState) { 114 // Random buggy state that doesn't decode?? 115 return "#" + trapState; 116 } else { 117 return trapReasonName(reason) + (recompFlag ? " recompiled" : ""); 118 } 119 } 120 121 122 123 static { 124 VM.registerVMInitializedObserver(new Observer() { 125 public void update(Observable o, Object data) { 126 initialize(VM.getVM().getTypeDataBase()); 127 } 128 }); 129 } 130 131 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 132 Type type = db.lookupType("methodDataOopDesc"); 133 baseOffset = type.getSize(); 134 135 size = new CIntField(type.getCIntegerField("_size"), 0); 136 method = new OopField(type.getOopField("_method"), 0); 137 138 VM.Flag[] flags = VM.getVM().getCommandLineFlags(); 139 for (int f = 0; f < flags.length; f++) { 140 VM.Flag flag = flags[f]; 141 if (flag.getName().equals("TypeProfileWidth")) { 142 TypeProfileWidth = (int)flag.getIntx(); 143 } else if (flag.getName().equals("BciProfileWidth")) { 144 BciProfileWidth = (int)flag.getIntx(); 145 } else if (flag.getName().equals("CompileThreshold")) { 146 CompileThreshold = (int)flag.getIntx(); 147 } 148 } 149 150 cellSize = (int)VM.getVM().getAddressSize(); 151 152 dataSize = new CIntField(type.getCIntegerField("_data_size"), 0); 153 data = type.getAddressField("_data[0]"); 154 155 sizeofMethodDataOopDesc = (int)type.getSize();; 156 157 Reason_many = db.lookupIntConstant("Deoptimization::Reason_many").intValue(); 158 Reason_none = db.lookupIntConstant("Deoptimization::Reason_none").intValue(); 159 Reason_LIMIT = db.lookupIntConstant("Deoptimization::Reason_LIMIT").intValue(); 160 Reason_RECORDED_LIMIT = db.lookupIntConstant("Deoptimization::Reason_RECORDED_LIMIT").intValue(); 161 162 trapReasonName = new String[Reason_LIMIT]; 163 164 // Find Deopt reasons 165 Iterator i = db.getIntConstants(); 166 String prefix = "Deoptimization::Reason_"; 167 while (i.hasNext()) { 168 String name = (String)i.next(); 169 if (name.startsWith(prefix)) { 170 // Strip prefix 171 if (!name.endsWith("Reason_many") && 172 !name.endsWith("Reason_LIMIT") && 173 !name.endsWith("Reason_RECORDED_LIMIT")) { 174 String trimmed = name.substring(prefix.length()); 175 int value = db.lookupIntConstant(name).intValue(); 176 if (trapReasonName[value] != null) { 177 throw new InternalError("duplicate reasons: " + trapReasonName[value] + " " + trimmed); 178 } 179 trapReasonName[value] = trimmed; 180 } 181 } 182 } 183 for (int index = 0; index < trapReasonName.length; index++) { 184 if (trapReasonName[index] == null) { 185 throw new InternalError("missing reason for " + index); 186 } 187 System.out.println(trapReasonName[index]); 188 } 189 } 190 191 MethodData(OopHandle handle, ObjectHeap heap) { 192 super(handle, heap); 193 } 194 195 public boolean isMethodData() { return true; } 196 197 private static long baseOffset; 198 private static CIntField size; 199 private static OopField method; 200 private static CIntField dataSize; 201 private static AddressField data; 202 203 public static int sizeofMethodDataOopDesc; 204 public static int cellSize; 205 206 public long getObjectSize() { 207 return alignObjectSize(size.getValue(this)); 208 } 209 210 public Method getMethod() { 211 return (Method) method.getValue(this); 212 } 213 214 public void printValueOn(PrintStream tty) { 215 Method m = getMethod(); 216 tty.print("MethodData for " + m.getName().asString() + m.getSignature().asString()); 217 } 218 219 public void iterateFields(OopVisitor visitor, boolean doVMFields) { 220 super.iterateFields(visitor, doVMFields); 221 if (doVMFields) { 222 visitor.doOop(method, true); 223 visitor.doCInt(size, true); 224 } 225 } 226 227 int dataSize() { 228 if (dataSize == null) { 229 return 0; 230 } else { 231 return (int)dataSize.getValue(this); 232 } 233 } 234 235 boolean outOfBounds(int dataIndex) { 236 return dataIndex >= dataSize(); 237 } 238 239 ProfileData dataAt(int dataIndex) { 240 if (outOfBounds(dataIndex)) { 241 return null; 242 } 243 DataLayout dataLayout = new DataLayout(this, dataIndex + (int)data.getOffset()); 244 245 switch (dataLayout.tag()) { 246 case DataLayout.noTag: 247 default: 248 throw new InternalError(dataIndex + " " + dataSize() + " " + dataLayout.tag()); 249 case DataLayout.bitDataTag: 250 return new BitData(dataLayout); 251 case DataLayout.counterDataTag: 252 return new CounterData(dataLayout); 253 case DataLayout.jumpDataTag: 254 return new JumpData(dataLayout); 255 case DataLayout.receiverTypeDataTag: 256 return new ReceiverTypeData(dataLayout); 257 case DataLayout.virtualCallDataTag: 258 return new VirtualCallData(dataLayout); 259 case DataLayout.retDataTag: 260 return new RetData(dataLayout); 261 case DataLayout.branchDataTag: 262 return new BranchData(dataLayout); 263 case DataLayout.multiBranchDataTag: 264 return new MultiBranchData(dataLayout); 265 } 266 } 267 268 int dpToDi(int dp) { 269 // this in an offset from the base of the MDO, so convert to offset into _data 270 return dp - (int)data.getOffset(); 271 } 272 273 int firstDi() { return 0; } 274 public ProfileData firstData() { return dataAt(firstDi()); } 275 public ProfileData nextData(ProfileData current) { 276 int currentIndex = dpToDi(current.dp()); 277 int nextIndex = currentIndex + current.sizeInBytes(); 278 return dataAt(nextIndex); 279 } 280 boolean isValid(ProfileData current) { return current != null; } 281 282 public void printDataOn(PrintStream st) { 283 ProfileData data = firstData(); 284 for ( ; isValid(data); data = nextData(data)) { 285 st.print(dpToDi(data.dp())); 286 st.print(" "); 287 // st->fillTo(6); 288 data.printDataOn(st); 289 } 290 } 291 292 private byte[] fetchDataAt(Address base, long offset, long size) { 293 byte[] result = new byte[(int)size]; 294 for (int i = 0; i < size; i++) { 295 result[i] = base.getJByteAt(offset + i); 296 } 297 return result; 298 } 299 300 public byte[] orig() { 301 // fetch the orig methodDataOopDesc data between header and dataSize 302 return fetchDataAt(this.getHandle(), 0, sizeofMethodDataOopDesc); 303 } 304 305 public long[] data() { 306 // Read the data as an array of intptr_t elements 307 OopHandle base = getHandle(); 308 long offset = data.getOffset(); 309 int elements = dataSize() / cellSize; 310 long[] result = new long[elements]; 311 for (int i = 0; i < elements; i++) { 312 Address value = base.getAddressAt(offset + i * MethodData.cellSize); 313 if (value != null) { 314 result[i] = value.minus(null); 315 } 316 } 317 return result; 318 } 319 320 // Get a measure of how much mileage the method has on it. 321 int mileageOf(Method method) { 322 long mileage = 0; 323 int iic = method.interpreterInvocationCount(); 324 if (mileage < iic) mileage = iic; 325 326 long ic = method.getInvocationCounter(); 327 long bc = method.getBackedgeCounter(); 328 329 long icval = ic >> 3; 330 if ((ic & 4) != 0) icval += CompileThreshold; 331 if (mileage < icval) mileage = icval; 332 long bcval = bc >> 3; 333 if ((bc & 4) != 0) bcval += CompileThreshold; 334 if (mileage < bcval) mileage = bcval; 335 return (int)mileage; 336 } 337 338 public int currentMileage() { 339 return 20000; 340 } 341 } |