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