1 /* 2 * Copyright (c) 2011, 2012, 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.ci; 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.oops.*; 32 import sun.jvm.hotspot.types.*; 33 34 public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKlass,ciMethod> { 35 static { 36 VM.registerVMInitializedObserver(new Observer() { 37 public void update(Observable o, Object data) { 38 initialize(VM.getVM().getTypeDataBase()); 39 } 40 }); 41 } 42 43 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 44 Type type = db.lookupType("ciMethodData"); 45 origField = type.getAddressField("_orig"); 46 currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0); 47 argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0); 48 argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0); 49 argLocalField = new CIntField(type.getCIntegerField("_arg_local"), 0); 50 eflagsField = new CIntField(type.getCIntegerField("_eflags"), 0); 51 hintDiField = new CIntField(type.getCIntegerField("_hint_di"), 0); 52 currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0); 53 dataField = type.getAddressField("_data"); 54 extraDataSizeField = new CIntField(type.getCIntegerField("_extra_data_size"), 0); 55 dataSizeField = new CIntField(type.getCIntegerField("_data_size"), 0); 56 stateField = new CIntField(type.getCIntegerField("_state"), 0); 57 Type typeMethodData = db.lookupType("MethodData"); 58 sizeofMethodDataOopDesc = (int)typeMethodData.getSize(); 59 parametersTypeDataDi = new CIntField(typeMethodData.getCIntegerField("_parameters_type_data_di"), 0); 60 } 61 62 private static AddressField origField; 63 private static CIntField currentMileageField; 64 private static CIntField argReturnedField; 65 private static CIntField argStackField; 66 private static CIntField argLocalField; 67 private static CIntField eflagsField; 68 private static CIntField hintDiField; 69 private static AddressField dataField; 70 private static CIntField extraDataSizeField; 71 private static CIntField dataSizeField; 72 private static CIntField stateField; 73 private static int sizeofMethodDataOopDesc; 74 private static CIntField parametersTypeDataDi; 75 76 public ciMethodData(Address addr) { 77 super(addr); 78 } 79 80 public ciKlass getKlassAtAddress(Address addr) { 81 return (ciKlass)ciObjectFactory.getMetadata(addr); 82 } 83 84 public ciMethod getMethodAtAddress(Address addr) { 85 return (ciMethod)ciObjectFactory.getMetadata(addr); 86 } 87 88 public void printKlassValueOn(ciKlass klass, PrintStream st) { 89 klass.printValueOn(st); 90 } 91 92 public void printMethodValueOn(ciMethod method, PrintStream st) { 93 method.printValueOn(st); 94 } 95 96 private byte[] fetchDataAt(Address base, long size) { 97 byte[] result = new byte[(int)size]; 98 for (int i = 0; i < size; i++) { 99 result[i] = base.getJByteAt(i); 100 } 101 return result; 102 } 103 104 public byte[] orig() { 105 // fetch the orig MethodData data between header and dataSize 106 Address base = getAddress().addOffsetTo(origField.getOffset()); 107 byte[] result = new byte[MethodData.sizeofMethodDataOopDesc]; 108 for (int i = 0; i < MethodData.sizeofMethodDataOopDesc; i++) { 109 result[i] = base.getJByteAt(i); 110 } 111 return result; 112 } 113 114 public long[] data() { 115 // Read the data as an array of intptr_t elements 116 Address base = dataField.getValue(getAddress()); 117 int elements = dataSize() / MethodData.cellSize; 118 long[] result = new long[elements]; 119 for (int i = 0; i < elements; i++) { 120 Address value = base.getAddressAt(i * MethodData.cellSize); 121 if (value != null) { 122 result[i] = value.minus(null); 123 } 124 } 125 return result; 126 } 127 128 int dataSize() { 129 return (int)dataSizeField.getValue(getAddress()); 130 } 131 132 int extraDataSize() { 133 return (int)extraDataSizeField.getValue(getAddress()); 134 } 135 136 int state() { 137 return (int)stateField.getValue(getAddress()); 138 } 139 140 int currentMileage() { 141 return (int)currentMileageField.getValue(getAddress()); 142 } 143 144 boolean outOfBounds(int dataIndex) { 145 return dataIndex >= dataSize(); 146 } 147 148 ParametersTypeData<ciKlass,ciMethod> parametersTypeData() { 149 Address base = getAddress().addOffsetTo(origField.getOffset()); 150 int di = (int)parametersTypeDataDi.getValue(base); 151 if (di == -1 || di == -2) { 152 return null; 153 } 154 DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), di); 155 return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout); 156 } 157 158 ProfileData dataAt(int dataIndex) { 159 if (outOfBounds(dataIndex)) { 160 return null; 161 } 162 DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), dataIndex); 163 164 switch (dataLayout.tag()) { 165 case DataLayout.noTag: 166 default: 167 throw new InternalError(); 168 case DataLayout.bitDataTag: 169 return new BitData(dataLayout); 170 case DataLayout.counterDataTag: 171 return new CounterData(dataLayout); 172 case DataLayout.jumpDataTag: 173 return new JumpData(dataLayout); 174 case DataLayout.receiverTypeDataTag: 175 return new ReceiverTypeData<ciKlass,ciMethod>(this, dataLayout); 176 case DataLayout.virtualCallDataTag: 177 return new VirtualCallData<ciKlass,ciMethod>(this, dataLayout); 178 case DataLayout.retDataTag: 179 return new RetData(dataLayout); 180 case DataLayout.branchDataTag: 181 return new BranchData(dataLayout); 182 case DataLayout.multiBranchDataTag: 183 return new MultiBranchData(dataLayout); 184 case DataLayout.callTypeDataTag: 185 return new CallTypeData<ciKlass,ciMethod>(this, dataLayout); 186 case DataLayout.virtualCallTypeDataTag: 187 return new VirtualCallTypeData<ciKlass,ciMethod>(this, dataLayout); 188 case DataLayout.parametersTypeDataTag: 189 return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout); 190 } 191 } 192 193 int dpToDi(int dp) { 194 return dp; 195 } 196 197 int firstDi() { return 0; } 198 ProfileData firstData() { return dataAt(firstDi()); } 199 ProfileData nextData(ProfileData current) { 200 int currentIndex = dpToDi(current.dp()); 201 int nextIndex = currentIndex + current.sizeInBytes(); 202 return dataAt(nextIndex); 203 } 204 boolean isValid(ProfileData current) { return current != null; } 205 206 DataLayout limitDataPosition() { 207 return new DataLayout(dataField.getValue(getAddress()), dataSize()); 208 } 209 DataLayout extraDataBase() { 210 return limitDataPosition(); 211 } 212 DataLayout extraDataLimit() { 213 return new DataLayout(dataField.getValue(getAddress()), dataSize() + extraDataSize()); 214 } 215 DataLayout nextExtra(DataLayout dataLayout) { 216 return new DataLayout(dataField.getValue(getAddress()), dataLayout.dp() + DataLayout.computeSizeInBytes(MethodData.extraNbCells(dataLayout))); 217 } 218 219 public void printDataOn(PrintStream st) { 220 if (parametersTypeData() != null) { 221 parametersTypeData().printDataOn(st); 222 } 223 ProfileData data = firstData(); 224 for ( ; isValid(data); data = nextData(data)) { 225 st.print(dpToDi(data.dp())); 226 st.print(" "); 227 // st->fillTo(6); 228 data.printDataOn(st); 229 } 230 st.println("--- Extra data:"); 231 DataLayout dp = extraDataBase(); 232 DataLayout end = extraDataLimit(); 233 for (;; dp = nextExtra(dp)) { 234 switch(dp.tag()) { 235 case DataLayout.noTag: 236 continue; 237 case DataLayout.bitDataTag: 238 data = new BitData(dp); 239 break; 240 case DataLayout.speculativeTrapDataTag: 241 data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp); 242 break; 243 case DataLayout.argInfoDataTag: 244 data = new ArgInfoData(dp); 245 dp = end; // ArgInfoData is at the end of extra data section. 246 break; 247 default: 248 throw new InternalError("unexpected tag " + dp.tag()); 249 } 250 st.print(dpToDi(data.dp())); 251 st.print(" "); 252 data.printDataOn(st); 253 if (dp == end) return; 254 } 255 } 256 257 int dumpReplayDataTypeHelper(PrintStream out, int round, int count, int index, ProfileData pdata, ciKlass k) { 258 if (k != null) { 259 if (round == 0) count++; 260 else out.print(" " + ((pdata.dp() + pdata.cellOffset(index)) / MethodData.cellSize) + " " + k.name()); 261 } 262 return count; 263 } 264 265 int dumpReplayDataReceiverTypeHelper(PrintStream out, int round, int count, ReceiverTypeData<ciKlass,ciMethod> vdata) { 266 for (int i = 0; i < vdata.rowLimit(); i++) { 267 ciKlass k = vdata.receiver(i); 268 count = dumpReplayDataTypeHelper(out, round, count, vdata.receiverCellIndex(i), vdata, k); 269 } 270 return count; 271 } 272 273 int dumpReplayDataCallTypeHelper(PrintStream out, int round, int count, CallTypeDataInterface<ciKlass> callTypeData) { 274 if (callTypeData.hasArguments()) { 275 for (int i = 0; i < callTypeData.numberOfArguments(); i++) { 276 count = dumpReplayDataTypeHelper(out, round, count, callTypeData.argumentTypeIndex(i), (ProfileData)callTypeData, callTypeData.argumentType(i)); 277 } 278 } 279 if (callTypeData.hasReturn()) { 280 count = dumpReplayDataTypeHelper(out, round, count, callTypeData.returnTypeIndex(), (ProfileData)callTypeData, callTypeData.returnType()); 281 } 282 return count; 283 } 284 285 int dumpReplayDataExtraDataHelper(PrintStream out, int round, int count) { 286 DataLayout dp = extraDataBase(); 287 DataLayout end = extraDataLimit(); 288 289 for (;dp != end; dp = nextExtra(dp)) { 290 switch(dp.tag()) { 291 case DataLayout.noTag: 292 case DataLayout.argInfoDataTag: 293 return count; 294 case DataLayout.bitDataTag: 295 break; 296 case DataLayout.speculativeTrapDataTag: { 297 SpeculativeTrapData<ciKlass,ciMethod> data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp); 298 ciMethod m = data.method(); 299 if (m != null) { 300 if (round == 0) { 301 count++; 302 } else { 303 out.print(" " + (dpToDi(data.dp() + data.cellOffset(SpeculativeTrapData.methodIndex())) / MethodData.cellSize) + " " + m.nameAsAscii()); 304 } 305 } 306 break; 307 } 308 default: 309 throw new InternalError("bad tag " + dp.tag()); 310 } 311 } 312 return count; 313 } 314 315 public void dumpReplayData(PrintStream out) { 316 MethodData mdo = (MethodData)getMetadata(); 317 Method method = mdo.getMethod(); 318 out.print("ciMethodData " + 319 method.nameAsAscii() + " " + 320 state() + " " + currentMileage()); 321 byte[] orig = orig(); 322 out.print(" orig " + orig.length); 323 for (int i = 0; i < orig.length; i++) { 324 out.print(" " + (orig[i] & 0xff)); 325 } 326 327 long[] data = data(); 328 out.print(" data " + data.length); 329 for (int i = 0; i < data.length; i++) { 330 out.print(" 0x" + Long.toHexString(data[i])); 331 } 332 int count = 0; 333 ParametersTypeData<ciKlass,ciMethod> parameters = parametersTypeData(); 334 for (int round = 0; round < 2; round++) { 335 if (round == 1) out.print(" oops " + count); 336 ProfileData pdata = firstData(); 337 for ( ; isValid(pdata); pdata = nextData(pdata)) { 338 if (pdata instanceof ReceiverTypeData) { 339 count = dumpReplayDataReceiverTypeHelper(out, round, count, (ReceiverTypeData<ciKlass,ciMethod>)pdata); 340 } 341 if (pdata instanceof CallTypeDataInterface) { 342 count = dumpReplayDataCallTypeHelper(out, round, count, (CallTypeDataInterface<ciKlass>)pdata); 343 } 344 } 345 if (parameters != null) { 346 for (int i = 0; i < parameters.numberOfParameters(); i++) { 347 count = dumpReplayDataTypeHelper(out, round, count, ParametersTypeData.typeIndex(i), parameters, parameters.type(i)); 348 } 349 } 350 } 351 count = 0; 352 for (int round = 0; round < 2; round++) { 353 if (round == 1) out.print(" methods " + count); 354 count = dumpReplayDataExtraDataHelper(out, round, count); 355 } 356 out.println(); 357 } 358 }