8026694: New type profiling points break compilation replay
Fixes compilation replay with new profiling points Reviewed-by: kvn, twisti
This commit is contained in:
parent
d7b76028a4
commit
7ef690b2c7
@ -64,7 +64,11 @@ public class ciEnv extends VMObject {
|
||||
}
|
||||
|
||||
public Compile compilerData() {
|
||||
return new Compile(compilerDataField.getValue(this.getAddress()));
|
||||
Address addr = compilerDataField.getValue(this.getAddress());
|
||||
if (addr == null) {
|
||||
return null;
|
||||
}
|
||||
return new Compile(addr);
|
||||
}
|
||||
|
||||
public ciObjectFactory factory() {
|
||||
@ -94,10 +98,7 @@ public class ciEnv extends VMObject {
|
||||
Method method = task.method();
|
||||
int entryBci = task.osrBci();
|
||||
int compLevel = task.compLevel();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.print("compile " + holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
out.print("compile " + method.nameAsAscii() + " " +
|
||||
entryBci + " " + compLevel);
|
||||
Compile compiler = compilerData();
|
||||
if (compiler != null) {
|
||||
|
@ -55,4 +55,9 @@ public class ciKlass extends ciType {
|
||||
public ciKlass(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public void printValueOn(PrintStream tty) {
|
||||
Klass k = (Klass)getMetadata();
|
||||
k.printValueOn(tty);
|
||||
}
|
||||
}
|
||||
|
@ -90,17 +90,23 @@ public class ciMethod extends ciMetadata {
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
Method method = (Method)getMetadata();
|
||||
NMethod nm = method.getNativeMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.println("ciMethod " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
method.getInvocationCount() + " " +
|
||||
method.getBackedgeCount() + " " +
|
||||
interpreterInvocationCount() + " " +
|
||||
interpreterThrowoutCount() + " " +
|
||||
instructionsSize());
|
||||
Method method = (Method)getMetadata();
|
||||
NMethod nm = method.getNativeMethod();
|
||||
out.println("ciMethod " +
|
||||
nameAsAscii() + " " +
|
||||
method.getInvocationCount() + " " +
|
||||
method.getBackedgeCount() + " " +
|
||||
interpreterInvocationCount() + " " +
|
||||
interpreterThrowoutCount() + " " +
|
||||
instructionsSize());
|
||||
}
|
||||
|
||||
public void printValueOn(PrintStream tty) {
|
||||
tty.print("ciMethod " + method().getName().asString() + method().getSignature().asString() + "@" + getAddress());
|
||||
}
|
||||
|
||||
public String nameAsAscii() {
|
||||
Method method = (Method)getMetadata();
|
||||
return method.nameAsAscii();
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
|
||||
public class ciMethodData extends ciMetadata {
|
||||
public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKlass,ciMethod> {
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
public void update(Observable o, Object data) {
|
||||
@ -54,7 +54,9 @@ public class ciMethodData extends ciMetadata {
|
||||
extraDataSizeField = new CIntField(type.getCIntegerField("_extra_data_size"), 0);
|
||||
dataSizeField = new CIntField(type.getCIntegerField("_data_size"), 0);
|
||||
stateField = new CIntField(type.getCIntegerField("_state"), 0);
|
||||
sizeofMethodDataOopDesc = (int)db.lookupType("MethodData").getSize();;
|
||||
Type typeMethodData = db.lookupType("MethodData");
|
||||
sizeofMethodDataOopDesc = (int)typeMethodData.getSize();
|
||||
parametersTypeDataDi = new CIntField(typeMethodData.getCIntegerField("_parameters_type_data_di"), 0);
|
||||
}
|
||||
|
||||
private static AddressField origField;
|
||||
@ -69,11 +71,28 @@ public class ciMethodData extends ciMetadata {
|
||||
private static CIntField dataSizeField;
|
||||
private static CIntField stateField;
|
||||
private static int sizeofMethodDataOopDesc;
|
||||
private static CIntField parametersTypeDataDi;
|
||||
|
||||
public ciMethodData(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public ciKlass getKlassAtAddress(Address addr) {
|
||||
return (ciKlass)ciObjectFactory.getMetadata(addr);
|
||||
}
|
||||
|
||||
public ciMethod getMethodAtAddress(Address addr) {
|
||||
return (ciMethod)ciObjectFactory.getMetadata(addr);
|
||||
}
|
||||
|
||||
public void printKlassValueOn(ciKlass klass, PrintStream st) {
|
||||
klass.printValueOn(st);
|
||||
}
|
||||
|
||||
public void printMethodValueOn(ciMethod method, PrintStream st) {
|
||||
method.printValueOn(st);
|
||||
}
|
||||
|
||||
private byte[] fetchDataAt(Address base, long size) {
|
||||
byte[] result = new byte[(int)size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -110,6 +129,10 @@ public class ciMethodData extends ciMetadata {
|
||||
return (int)dataSizeField.getValue(getAddress());
|
||||
}
|
||||
|
||||
int extraDataSize() {
|
||||
return (int)extraDataSizeField.getValue(getAddress());
|
||||
}
|
||||
|
||||
int state() {
|
||||
return (int)stateField.getValue(getAddress());
|
||||
}
|
||||
@ -122,6 +145,16 @@ public class ciMethodData extends ciMetadata {
|
||||
return dataIndex >= dataSize();
|
||||
}
|
||||
|
||||
ParametersTypeData<ciKlass,ciMethod> parametersTypeData() {
|
||||
Address base = getAddress().addOffsetTo(origField.getOffset());
|
||||
int di = (int)parametersTypeDataDi.getValue(base);
|
||||
if (di == -1) {
|
||||
return null;
|
||||
}
|
||||
DataLayout dataLayout = new DataLayout(dataField.getValue(getAddress()), di);
|
||||
return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout);
|
||||
}
|
||||
|
||||
ProfileData dataAt(int dataIndex) {
|
||||
if (outOfBounds(dataIndex)) {
|
||||
return null;
|
||||
@ -139,15 +172,21 @@ public class ciMethodData extends ciMetadata {
|
||||
case DataLayout.jumpDataTag:
|
||||
return new JumpData(dataLayout);
|
||||
case DataLayout.receiverTypeDataTag:
|
||||
return new ciReceiverTypeData(dataLayout);
|
||||
return new ReceiverTypeData<ciKlass,ciMethod>(this, dataLayout);
|
||||
case DataLayout.virtualCallDataTag:
|
||||
return new ciVirtualCallData(dataLayout);
|
||||
return new VirtualCallData<ciKlass,ciMethod>(this, dataLayout);
|
||||
case DataLayout.retDataTag:
|
||||
return new RetData(dataLayout);
|
||||
case DataLayout.branchDataTag:
|
||||
return new BranchData(dataLayout);
|
||||
case DataLayout.multiBranchDataTag:
|
||||
return new MultiBranchData(dataLayout);
|
||||
case DataLayout.callTypeDataTag:
|
||||
return new CallTypeData<ciKlass,ciMethod>(this, dataLayout);
|
||||
case DataLayout.virtualCallTypeDataTag:
|
||||
return new VirtualCallTypeData<ciKlass,ciMethod>(this, dataLayout);
|
||||
case DataLayout.parametersTypeDataTag:
|
||||
return new ParametersTypeData<ciKlass,ciMethod>(this, dataLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +203,23 @@ public class ciMethodData extends ciMetadata {
|
||||
}
|
||||
boolean isValid(ProfileData current) { return current != null; }
|
||||
|
||||
DataLayout limitDataPosition() {
|
||||
return new DataLayout(dataField.getValue(getAddress()), dataSize());
|
||||
}
|
||||
DataLayout extraDataBase() {
|
||||
return limitDataPosition();
|
||||
}
|
||||
DataLayout extraDataLimit() {
|
||||
return new DataLayout(dataField.getValue(getAddress()), dataSize() + extraDataSize());
|
||||
}
|
||||
DataLayout nextExtra(DataLayout dataLayout) {
|
||||
return new DataLayout(dataField.getValue(getAddress()), dataLayout.dp() + DataLayout.computeSizeInBytes(MethodData.extraNbCells(dataLayout)));
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
if (parametersTypeData() != null) {
|
||||
parametersTypeData().printDataOn(st);
|
||||
}
|
||||
ProfileData data = firstData();
|
||||
for ( ; isValid(data); data = nextData(data)) {
|
||||
st.print(dpToDi(data.dp()));
|
||||
@ -172,16 +227,96 @@ public class ciMethodData extends ciMetadata {
|
||||
// st->fillTo(6);
|
||||
data.printDataOn(st);
|
||||
}
|
||||
st.println("--- Extra data:");
|
||||
DataLayout dp = extraDataBase();
|
||||
DataLayout end = extraDataLimit();
|
||||
for (;; dp = nextExtra(dp)) {
|
||||
switch(dp.tag()) {
|
||||
case DataLayout.noTag:
|
||||
continue;
|
||||
case DataLayout.bitDataTag:
|
||||
data = new BitData(dp);
|
||||
break;
|
||||
case DataLayout.speculativeTrapDataTag:
|
||||
data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp);
|
||||
break;
|
||||
case DataLayout.argInfoDataTag:
|
||||
data = new ArgInfoData(dp);
|
||||
dp = end; // ArgInfoData is at the end of extra data section.
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unexpected tag " + dp.tag());
|
||||
}
|
||||
st.print(dpToDi(data.dp()));
|
||||
st.print(" ");
|
||||
data.printDataOn(st);
|
||||
if (dp == end) return;
|
||||
}
|
||||
}
|
||||
|
||||
int dumpReplayDataTypeHelper(PrintStream out, int round, int count, int index, ProfileData pdata, ciKlass k) {
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " + ((pdata.dp() + pdata.cellOffset(index)) / MethodData.cellSize) + " " + k.name());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataReceiverTypeHelper(PrintStream out, int round, int count, ReceiverTypeData<ciKlass,ciMethod> vdata) {
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
ciKlass k = vdata.receiver(i);
|
||||
count = dumpReplayDataTypeHelper(out, round, count, vdata.receiverCellIndex(i), vdata, k);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataCallTypeHelper(PrintStream out, int round, int count, CallTypeDataInterface<ciKlass> callTypeData) {
|
||||
if (callTypeData.hasArguments()) {
|
||||
for (int i = 0; i < callTypeData.numberOfArguments(); i++) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, callTypeData.argumentTypeIndex(i), (ProfileData)callTypeData, callTypeData.argumentType(i));
|
||||
}
|
||||
}
|
||||
if (callTypeData.hasReturn()) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, callTypeData.returnTypeIndex(), (ProfileData)callTypeData, callTypeData.returnType());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataExtraDataHelper(PrintStream out, int round, int count) {
|
||||
DataLayout dp = extraDataBase();
|
||||
DataLayout end = extraDataLimit();
|
||||
|
||||
for (;dp != end; dp = nextExtra(dp)) {
|
||||
switch(dp.tag()) {
|
||||
case DataLayout.noTag:
|
||||
case DataLayout.argInfoDataTag:
|
||||
return count;
|
||||
case DataLayout.bitDataTag:
|
||||
break;
|
||||
case DataLayout.speculativeTrapDataTag: {
|
||||
SpeculativeTrapData<ciKlass,ciMethod> data = new SpeculativeTrapData<ciKlass,ciMethod>(this, dp);
|
||||
ciMethod m = data.method();
|
||||
if (m != null) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out.print(" " + (dpToDi(data.dp() + data.cellOffset(SpeculativeTrapData.methodIndex())) / MethodData.cellSize) + " " + m.nameAsAscii());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new InternalError("bad tag " + dp.tag());
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
MethodData mdo = (MethodData)getMetadata();
|
||||
Method method = mdo.getMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.print("ciMethodData " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
method.nameAsAscii() + " " +
|
||||
state() + " " + currentMileage());
|
||||
byte[] orig = orig();
|
||||
out.print(" orig " + orig.length);
|
||||
@ -195,30 +330,28 @@ public class ciMethodData extends ciMetadata {
|
||||
out.print(" 0x" + Long.toHexString(data[i]));
|
||||
}
|
||||
int count = 0;
|
||||
ParametersTypeData<ciKlass,ciMethod> parameters = parametersTypeData();
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" oops " + count);
|
||||
ProfileData pdata = firstData();
|
||||
for ( ; isValid(pdata); pdata = nextData(pdata)) {
|
||||
if (pdata instanceof ciReceiverTypeData) {
|
||||
ciReceiverTypeData vdata = (ciReceiverTypeData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
ciKlass k = vdata.receiverAt(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize) + " " + k.name());
|
||||
}
|
||||
}
|
||||
} else if (pdata instanceof ciVirtualCallData) {
|
||||
ciVirtualCallData vdata = (ciVirtualCallData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
ciKlass k = vdata.receiverAt(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize + " " + k.name()));
|
||||
}
|
||||
}
|
||||
if (pdata instanceof ReceiverTypeData) {
|
||||
count = dumpReplayDataReceiverTypeHelper(out, round, count, (ReceiverTypeData<ciKlass,ciMethod>)pdata);
|
||||
}
|
||||
if (pdata instanceof CallTypeDataInterface) {
|
||||
count = dumpReplayDataCallTypeHelper(out, round, count, (CallTypeDataInterface<ciKlass>)pdata);
|
||||
}
|
||||
}
|
||||
if (parameters != null) {
|
||||
for (int i = 0; i < parameters.numberOfParameters(); i++) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, ParametersTypeData.typeIndex(i), parameters, parameters.type(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" methods " + count);
|
||||
count = dumpReplayDataExtraDataHelper(out, round, count);
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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
|
||||
@ -22,31 +22,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.ci;
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class ciVirtualCallData extends VirtualCallData {
|
||||
public ciVirtualCallData(DataLayout data) {
|
||||
super(data);
|
||||
public class ArgInfoData extends ArrayData {
|
||||
|
||||
public ArgInfoData(DataLayout layout) {
|
||||
super(layout);
|
||||
}
|
||||
|
||||
public Klass receiver(int row) {
|
||||
throw new InternalError("should not call");
|
||||
int numberOfArgs() {
|
||||
return arrayLen();
|
||||
}
|
||||
|
||||
public ciKlass receiverAt(int row) {
|
||||
//assert((uint)row < rowLimit(), "oob");
|
||||
ciMetadata recv = ciObjectFactory.getMetadata(addressAt(receiverCellIndex(row)));
|
||||
if (recv != null && !(recv instanceof ciKlass)) {
|
||||
System.err.println(recv);
|
||||
int argModified(int arg) {
|
||||
return arrayUintAt(arg);
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
printShared(st, "ArgInfoData");
|
||||
int nargs = numberOfArgs();
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
st.print(" 0x" + Integer.toHexString(argModified(i)));
|
||||
}
|
||||
//assert(recv == NULL || recv->isKlass(), "wrong type");
|
||||
return (ciKlass)recv;
|
||||
st.println();
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// CallTypeData
|
||||
//
|
||||
// A CallTypeData is used to access profiling information about a non
|
||||
// virtual call for which we collect type information about arguments
|
||||
// and return value.
|
||||
public class CallTypeData<K,M> extends CounterData implements CallTypeDataInterface<K> {
|
||||
final TypeStackSlotEntries<K,M> args;
|
||||
final ReturnTypeEntry<K,M> ret;
|
||||
|
||||
int cellCountGlobalOffset() {
|
||||
return CounterData.staticCellCount() + TypeEntriesAtCall.cellCountLocalOffset();
|
||||
}
|
||||
|
||||
int cellCountNoHeader() {
|
||||
return uintAt(cellCountGlobalOffset());
|
||||
}
|
||||
|
||||
public CallTypeData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(layout);
|
||||
args = new TypeStackSlotEntries<K,M>(methodData, this, CounterData.staticCellCount()+TypeEntriesAtCall.headerCellCount(), numberOfArguments());
|
||||
ret = new ReturnTypeEntry<K,M>(methodData, this, cellCount() - ReturnTypeEntry.staticCellCount());
|
||||
}
|
||||
|
||||
static int staticCellCount() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int cellCount() {
|
||||
return CounterData.staticCellCount() +
|
||||
TypeEntriesAtCall.headerCellCount() +
|
||||
intAt(cellCountGlobalOffset());
|
||||
}
|
||||
|
||||
public int numberOfArguments() {
|
||||
return cellCountNoHeader() / TypeStackSlotEntries.perArgCount();
|
||||
}
|
||||
|
||||
public boolean hasArguments() {
|
||||
return cellCountNoHeader() >= TypeStackSlotEntries.perArgCount();
|
||||
}
|
||||
|
||||
public K argumentType(int i) {
|
||||
return args.type(i);
|
||||
}
|
||||
|
||||
public boolean hasReturn() {
|
||||
return (cellCountNoHeader() % TypeStackSlotEntries.perArgCount()) != 0;
|
||||
}
|
||||
|
||||
public K returnType() {
|
||||
return ret.type();
|
||||
}
|
||||
|
||||
public int argumentTypeIndex(int i) {
|
||||
return args.typeIndex(i);
|
||||
}
|
||||
|
||||
public int returnTypeIndex() {
|
||||
return ret.typeIndex();
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
super.printDataOn(st);
|
||||
if (hasArguments()) {
|
||||
tab(st);
|
||||
st.print("argument types");
|
||||
args.printDataOn(st);
|
||||
}
|
||||
if (hasReturn()) {
|
||||
tab(st);
|
||||
st.print("return type");
|
||||
ret.printDataOn(st);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
public interface CallTypeDataInterface<K> {
|
||||
int numberOfArguments();
|
||||
boolean hasArguments();
|
||||
K argumentType(int i);
|
||||
boolean hasReturn();
|
||||
K returnType();
|
||||
int argumentTypeIndex(int i);
|
||||
int returnTypeIndex();
|
||||
}
|
@ -41,6 +41,11 @@ public class DataLayout {
|
||||
public static final int retDataTag = 6;
|
||||
public static final int branchDataTag = 7;
|
||||
public static final int multiBranchDataTag = 8;
|
||||
public static final int argInfoDataTag = 9;
|
||||
public static final int callTypeDataTag = 10;
|
||||
public static final int virtualCallTypeDataTag = 11;
|
||||
public static final int parametersTypeDataTag = 12;
|
||||
public static final int speculativeTrapDataTag = 13;
|
||||
|
||||
// The _struct._flags word is formatted as [trapState:4 | flags:4].
|
||||
// The trap state breaks down further as [recompile:1 | reason:3].
|
||||
@ -61,8 +66,6 @@ public class DataLayout {
|
||||
|
||||
private int offset;
|
||||
|
||||
private boolean handlized;
|
||||
|
||||
public DataLayout(MethodData d, int o) {
|
||||
data = d.getAddress();
|
||||
offset = o;
|
||||
@ -71,7 +74,6 @@ public class DataLayout {
|
||||
public DataLayout(Address d, int o) {
|
||||
data = d;
|
||||
offset = o;
|
||||
handlized = true;
|
||||
}
|
||||
|
||||
public int dp() { return offset; }
|
||||
@ -90,12 +92,7 @@ public class DataLayout {
|
||||
}
|
||||
|
||||
public Address addressAt(int index) {
|
||||
OopHandle handle;
|
||||
if (handlized) {
|
||||
return data.getAddressAt(offset + cellOffset(index));
|
||||
} else {
|
||||
return data.getOopHandleAt(offset + cellOffset(index));
|
||||
}
|
||||
return data.getAddressAt(offset + cellOffset(index));
|
||||
}
|
||||
|
||||
// Every data layout begins with a header. This header
|
||||
@ -128,7 +125,7 @@ public class DataLayout {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int computeSizeInBytes(int cellCount) {
|
||||
static public int computeSizeInBytes(int cellCount) {
|
||||
return headerSizeInBytes() + cellCount * MethodData.cellSize;
|
||||
}
|
||||
|
||||
|
@ -354,9 +354,7 @@ public class Method extends Metadata {
|
||||
}
|
||||
Klass holder = getMethodHolder();
|
||||
out.println("ciMethod " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(getName().asString()) + " " +
|
||||
getSignature().asString() + " " +
|
||||
nameAsAscii() + " " +
|
||||
getInvocationCount() + " " +
|
||||
getBackedgeCount() + " " +
|
||||
interpreterInvocationCount() + " " +
|
||||
@ -371,4 +369,10 @@ public class Method extends Metadata {
|
||||
public int interpreterInvocationCount() {
|
||||
return getMethodCounters().interpreterInvocationCount();
|
||||
}
|
||||
|
||||
public String nameAsAscii() {
|
||||
return getMethodHolder().getName().asString() + " " +
|
||||
OopUtilities.escapeString(getName().asString()) + " " +
|
||||
getSignature().asString();
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// A MethodData provides interpreter profiling information
|
||||
|
||||
public class MethodData extends Metadata {
|
||||
public class MethodData extends Metadata implements MethodDataInterface<Klass,Method> {
|
||||
static int TypeProfileWidth = 2;
|
||||
static int BciProfileWidth = 2;
|
||||
static int CompileThreshold;
|
||||
@ -152,6 +152,8 @@ public class MethodData extends Metadata {
|
||||
dataSize = new CIntField(type.getCIntegerField("_data_size"), 0);
|
||||
data = type.getAddressField("_data[0]");
|
||||
|
||||
parametersTypeDataDi = new CIntField(type.getCIntegerField("_parameters_type_data_di"), 0);
|
||||
|
||||
sizeofMethodDataOopDesc = (int)type.getSize();;
|
||||
|
||||
Reason_many = db.lookupIntConstant("Deoptimization::Reason_many").intValue();
|
||||
@ -191,6 +193,22 @@ public class MethodData extends Metadata {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public Klass getKlassAtAddress(Address addr) {
|
||||
return (Klass)Metadata.instantiateWrapperFor(addr);
|
||||
}
|
||||
|
||||
public Method getMethodAtAddress(Address addr) {
|
||||
return (Method)Metadata.instantiateWrapperFor(addr);
|
||||
}
|
||||
|
||||
public void printKlassValueOn(Klass klass, PrintStream st) {
|
||||
klass.printValueOn(st);
|
||||
}
|
||||
|
||||
public void printMethodValueOn(Method method, PrintStream st) {
|
||||
method.printValueOn(st);
|
||||
}
|
||||
|
||||
public boolean isMethodData() { return true; }
|
||||
|
||||
private static long baseOffset;
|
||||
@ -198,7 +216,7 @@ public class MethodData extends Metadata {
|
||||
private static MetadataField method;
|
||||
private static CIntField dataSize;
|
||||
private static AddressField data;
|
||||
|
||||
private static CIntField parametersTypeDataDi;
|
||||
public static int sizeofMethodDataOopDesc;
|
||||
public static int cellSize;
|
||||
|
||||
@ -225,6 +243,27 @@ public class MethodData extends Metadata {
|
||||
}
|
||||
}
|
||||
|
||||
int sizeInBytes() {
|
||||
if (size == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int)size.getValue(getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
int size() {
|
||||
return (int)Oop.alignObjectSize(VM.getVM().alignUp(sizeInBytes(), VM.getVM().getBytesPerWord())/VM.getVM().getBytesPerWord());
|
||||
}
|
||||
|
||||
ParametersTypeData<Klass,Method> parametersTypeData() {
|
||||
int di = (int)parametersTypeDataDi.getValue(getAddress());
|
||||
if (di == -1) {
|
||||
return null;
|
||||
}
|
||||
DataLayout dataLayout = new DataLayout(this, di + (int)data.getOffset());
|
||||
return new ParametersTypeData<Klass,Method>(this, dataLayout);
|
||||
}
|
||||
|
||||
boolean outOfBounds(int dataIndex) {
|
||||
return dataIndex >= dataSize();
|
||||
}
|
||||
@ -246,15 +285,21 @@ public class MethodData extends Metadata {
|
||||
case DataLayout.jumpDataTag:
|
||||
return new JumpData(dataLayout);
|
||||
case DataLayout.receiverTypeDataTag:
|
||||
return new ReceiverTypeData(dataLayout);
|
||||
return new ReceiverTypeData<Klass,Method>(this, dataLayout);
|
||||
case DataLayout.virtualCallDataTag:
|
||||
return new VirtualCallData(dataLayout);
|
||||
return new VirtualCallData<Klass,Method>(this, dataLayout);
|
||||
case DataLayout.retDataTag:
|
||||
return new RetData(dataLayout);
|
||||
case DataLayout.branchDataTag:
|
||||
return new BranchData(dataLayout);
|
||||
case DataLayout.multiBranchDataTag:
|
||||
return new MultiBranchData(dataLayout);
|
||||
case DataLayout.callTypeDataTag:
|
||||
return new CallTypeData<Klass,Method>(this, dataLayout);
|
||||
case DataLayout.virtualCallTypeDataTag:
|
||||
return new VirtualCallTypeData<Klass,Method>(this, dataLayout);
|
||||
case DataLayout.parametersTypeDataTag:
|
||||
return new ParametersTypeData<Klass,Method>(this, dataLayout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +317,42 @@ public class MethodData extends Metadata {
|
||||
}
|
||||
boolean isValid(ProfileData current) { return current != null; }
|
||||
|
||||
DataLayout limitDataPosition() {
|
||||
return new DataLayout(this, dataSize() + (int)data.getOffset());
|
||||
}
|
||||
|
||||
DataLayout extraDataBase() {
|
||||
return limitDataPosition();
|
||||
}
|
||||
|
||||
DataLayout extraDataLimit() {
|
||||
return new DataLayout(this, sizeInBytes());
|
||||
}
|
||||
|
||||
static public int extraNbCells(DataLayout dataLayout) {
|
||||
int nbCells = 0;
|
||||
switch(dataLayout.tag()) {
|
||||
case DataLayout.bitDataTag:
|
||||
case DataLayout.noTag:
|
||||
nbCells = BitData.staticCellCount();
|
||||
break;
|
||||
case DataLayout.speculativeTrapDataTag:
|
||||
nbCells = SpeculativeTrapData.staticCellCount();
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unexpected tag " + dataLayout.tag());
|
||||
}
|
||||
return nbCells;
|
||||
}
|
||||
|
||||
DataLayout nextExtra(DataLayout dataLayout) {
|
||||
return new DataLayout(this, dataLayout.dp() + DataLayout.computeSizeInBytes(extraNbCells(dataLayout)));
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
if (parametersTypeData() != null) {
|
||||
parametersTypeData().printDataOn(st);
|
||||
}
|
||||
ProfileData data = firstData();
|
||||
for ( ; isValid(data); data = nextData(data)) {
|
||||
st.print(dpToDi(data.dp()));
|
||||
@ -280,6 +360,31 @@ public class MethodData extends Metadata {
|
||||
// st->fillTo(6);
|
||||
data.printDataOn(st);
|
||||
}
|
||||
st.println("--- Extra data:");
|
||||
DataLayout dp = extraDataBase();
|
||||
DataLayout end = extraDataLimit();
|
||||
for (;; dp = nextExtra(dp)) {
|
||||
switch(dp.tag()) {
|
||||
case DataLayout.noTag:
|
||||
continue;
|
||||
case DataLayout.bitDataTag:
|
||||
data = new BitData(dp);
|
||||
break;
|
||||
case DataLayout.speculativeTrapDataTag:
|
||||
data = new SpeculativeTrapData<Klass,Method>(this, dp);
|
||||
break;
|
||||
case DataLayout.argInfoDataTag:
|
||||
data = new ArgInfoData(dp);
|
||||
dp = end; // ArgInfoData is at the end of extra data section.
|
||||
break;
|
||||
default:
|
||||
throw new InternalError("unexpected tag " + dp.tag());
|
||||
}
|
||||
st.print(dpToDi(data.dp()));
|
||||
st.print(" ");
|
||||
data.printDataOn(st);
|
||||
if (dp == end) return;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] fetchDataAt(Address base, long offset, long size) {
|
||||
@ -332,14 +437,71 @@ public class MethodData extends Metadata {
|
||||
return 20000;
|
||||
}
|
||||
|
||||
int dumpReplayDataTypeHelper(PrintStream out, int round, int count, int index, ProfileData pdata, Klass k) {
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " +
|
||||
(dpToDi(pdata.dp() +
|
||||
pdata.cellOffset(index)) / cellSize) + " " +
|
||||
k.getName().asString());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataReceiverTypeHelper(PrintStream out, int round, int count, ReceiverTypeData<Klass,Method> vdata) {
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
Klass k = vdata.receiver(i);
|
||||
count = dumpReplayDataTypeHelper(out, round, count, vdata.receiverCellIndex(i), vdata, k);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataCallTypeHelper(PrintStream out, int round, int count, CallTypeDataInterface<Klass> callTypeData) {
|
||||
if (callTypeData.hasArguments()) {
|
||||
for (int i = 0; i < callTypeData.numberOfArguments(); i++) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, callTypeData.argumentTypeIndex(i), (ProfileData)callTypeData, callTypeData.argumentType(i));
|
||||
}
|
||||
}
|
||||
if (callTypeData.hasReturn()) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, callTypeData.returnTypeIndex(), (ProfileData)callTypeData, callTypeData.returnType());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int dumpReplayDataExtraDataHelper(PrintStream out, int round, int count) {
|
||||
DataLayout dp = extraDataBase();
|
||||
DataLayout end = extraDataLimit();
|
||||
|
||||
for (;dp != end; dp = nextExtra(dp)) {
|
||||
switch(dp.tag()) {
|
||||
case DataLayout.noTag:
|
||||
case DataLayout.argInfoDataTag:
|
||||
return count;
|
||||
case DataLayout.bitDataTag:
|
||||
break;
|
||||
case DataLayout.speculativeTrapDataTag: {
|
||||
SpeculativeTrapData<Klass,Method> data = new SpeculativeTrapData<Klass,Method>(this, dp);
|
||||
Method m = data.method();
|
||||
if (m != null) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out.print(" " + (dpToDi(data.dp() + data.cellOffset(SpeculativeTrapData.methodIndex())) / cellSize) + " " + m.nameAsAscii());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new InternalError("bad tag " + dp.tag());
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
Method method = getMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.print("ciMethodData " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
"2" + " " +
|
||||
out.print("ciMethodData " + method.nameAsAscii()
|
||||
+ " " + "2" + " " +
|
||||
currentMileage());
|
||||
byte[] orig = orig();
|
||||
out.print(" orig " + orig.length);
|
||||
@ -353,36 +515,28 @@ public class MethodData extends Metadata {
|
||||
out.print(" 0x" + Long.toHexString(data[i]));
|
||||
}
|
||||
int count = 0;
|
||||
ParametersTypeData<Klass,Method> parameters = parametersTypeData();
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" oops " + count);
|
||||
ProfileData pdata = firstData();
|
||||
for ( ; isValid(pdata); pdata = nextData(pdata)) {
|
||||
if (pdata instanceof ReceiverTypeData) {
|
||||
ReceiverTypeData vdata = (ReceiverTypeData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
Klass k = vdata.receiver(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " +
|
||||
(dpToDi(vdata.dp() +
|
||||
vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " +
|
||||
k.getName().asString());
|
||||
}
|
||||
}
|
||||
} else if (pdata instanceof VirtualCallData) {
|
||||
VirtualCallData vdata = (VirtualCallData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
Klass k = vdata.receiver(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " +
|
||||
(dpToDi(vdata.dp() +
|
||||
vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " +
|
||||
k.getName().asString());
|
||||
}
|
||||
}
|
||||
count = dumpReplayDataReceiverTypeHelper(out, round, count, (ReceiverTypeData<Klass,Method>)pdata);
|
||||
}
|
||||
if (pdata instanceof CallTypeDataInterface) {
|
||||
count = dumpReplayDataCallTypeHelper(out, round, count, (CallTypeDataInterface<Klass>)pdata);
|
||||
}
|
||||
}
|
||||
if (parameters != null) {
|
||||
for (int i = 0; i < parameters.numberOfParameters(); i++) {
|
||||
count = dumpReplayDataTypeHelper(out, round, count, ParametersTypeData.typeIndex(i), parameters, parameters.type(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" methods " + count);
|
||||
count = dumpReplayDataExtraDataHelper(out, round, count);
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public interface MethodDataInterface<K, M> {
|
||||
K getKlassAtAddress(Address addr);
|
||||
M getMethodAtAddress(Address addr);
|
||||
void printKlassValueOn(K klass, PrintStream st);
|
||||
void printMethodValueOn(M klass, PrintStream st);
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// ParametersTypeData
|
||||
//
|
||||
// A ParametersTypeData is used to access profiling information about
|
||||
// types of parameters to a method
|
||||
public class ParametersTypeData<K,M> extends ArrayData {
|
||||
final TypeStackSlotEntries<K,M> parameters;
|
||||
|
||||
static int stackSlotLocalOffset(int i) {
|
||||
return arrayStartOffSet + TypeStackSlotEntries.stackSlotLocalOffset(i);
|
||||
}
|
||||
|
||||
static int typeLocalOffset(int i) {
|
||||
return arrayStartOffSet + TypeStackSlotEntries.typeLocalOffset(i);
|
||||
}
|
||||
|
||||
public ParametersTypeData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(layout);
|
||||
parameters = new TypeStackSlotEntries<K,M>(methodData, this, 1, numberOfParameters());
|
||||
}
|
||||
|
||||
public int numberOfParameters() {
|
||||
return arrayLen() / TypeStackSlotEntries.perArgCount();
|
||||
}
|
||||
|
||||
int stackSlot(int i) {
|
||||
return parameters.stackSlot(i);
|
||||
}
|
||||
|
||||
public K type(int i) {
|
||||
return parameters.type(i);
|
||||
}
|
||||
|
||||
static public int typeIndex(int i) {
|
||||
return typeLocalOffset(i);
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
st.print("parameter types");
|
||||
parameters.printDataOn(st);
|
||||
}
|
||||
}
|
@ -37,13 +37,15 @@ import sun.jvm.hotspot.utilities.*;
|
||||
// dynamic type check. It consists of a counter which counts the total times
|
||||
// that the check is reached, and a series of (Klass, count) pairs
|
||||
// which are used to store a type profile for the receiver of the check.
|
||||
public class ReceiverTypeData extends CounterData {
|
||||
public class ReceiverTypeData<K,M> extends CounterData {
|
||||
static final int receiver0Offset = counterCellCount;
|
||||
static final int count0Offset = receiver0Offset + 1;
|
||||
static final int receiverTypeRowCellCount = (count0Offset + 1) - receiver0Offset;
|
||||
final MethodDataInterface<K,M> methodData;
|
||||
|
||||
public ReceiverTypeData(DataLayout layout) {
|
||||
public ReceiverTypeData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(layout);
|
||||
this.methodData = methodData;
|
||||
//assert(layout.tag() == DataLayout.receiverTypeDataTag ||
|
||||
// layout.tag() == DataLayout.virtualCallDataTag, "wrong type");
|
||||
}
|
||||
@ -73,14 +75,14 @@ public class ReceiverTypeData extends CounterData {
|
||||
// gc; it does not assert the receiver is a klass. During compaction of the
|
||||
// perm gen, the klass may already have moved, so the isKlass() predicate
|
||||
// would fail. The 'normal' version should be used whenever possible.
|
||||
Klass receiverUnchecked(int row) {
|
||||
K receiverUnchecked(int row) {
|
||||
//assert(row < rowLimit(), "oob");
|
||||
Address recv = addressAt(receiverCellIndex(row));
|
||||
return (Klass)Metadata.instantiateWrapperFor(recv);
|
||||
return methodData.getKlassAtAddress(recv);
|
||||
}
|
||||
|
||||
public Klass receiver(int row) {
|
||||
Klass recv = receiverUnchecked(row);
|
||||
public K receiver(int row) {
|
||||
K recv = receiverUnchecked(row);
|
||||
//assert(recv == NULL || ((oop)recv).isKlass(), "wrong type");
|
||||
return recv;
|
||||
}
|
||||
@ -111,7 +113,7 @@ public class ReceiverTypeData extends CounterData {
|
||||
for (row = 0; row < rowLimit(); row++) {
|
||||
if (receiver(row) != null) {
|
||||
tab(st);
|
||||
receiver(row).printValueOn(st);
|
||||
methodData.printKlassValueOn(receiver(row), st);
|
||||
st.println("(" + receiverCount(row) + ")");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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
|
||||
@ -22,32 +22,39 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.ci;
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class ciReceiverTypeData extends ReceiverTypeData {
|
||||
public ciReceiverTypeData(DataLayout data) {
|
||||
super(data);
|
||||
// Type entry used for return from a call. A single cell to record the
|
||||
// type.
|
||||
public class ReturnTypeEntry<K,M> extends TypeEntries<K,M> {
|
||||
static final int cellCount = 1;
|
||||
|
||||
ReturnTypeEntry(MethodDataInterface<K,M> methodData, ProfileData pd, int baseOff) {
|
||||
super(methodData, pd, baseOff);
|
||||
}
|
||||
|
||||
public Klass receiver(int row) {
|
||||
throw new InternalError("should not call");
|
||||
K type() {
|
||||
return validKlass(baseOff);
|
||||
}
|
||||
|
||||
public ciKlass receiverAt(int row) {
|
||||
//assert((uint)row < rowLimit(), "oob");
|
||||
ciMetadata recv = ciObjectFactory.getMetadata(addressAt(receiverCellIndex(row)));
|
||||
if (recv != null && !(recv instanceof ciKlass)) {
|
||||
System.err.println(recv);
|
||||
}
|
||||
//assert(recv == NULL || recv->isKlass(), "wrong type");
|
||||
return (ciKlass)recv;
|
||||
static int staticCellCount() {
|
||||
return cellCount;
|
||||
}
|
||||
|
||||
int typeIndex() {
|
||||
return baseOff;
|
||||
}
|
||||
|
||||
void printDataOn(PrintStream st) {
|
||||
pd.tab(st);
|
||||
printKlass(st, baseOff);
|
||||
st.println();
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// SpeculativeTrapData
|
||||
//
|
||||
// A SpeculativeTrapData is used to record traps due to type
|
||||
// speculation. It records the root of the compilation.
|
||||
public class SpeculativeTrapData<K, M> extends ProfileData {
|
||||
static final int speculativeTrapMethod = 0;
|
||||
static final int speculativeTrapCellCount = 1;
|
||||
final MethodDataInterface<K, M> methodData;
|
||||
|
||||
public SpeculativeTrapData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(layout);
|
||||
this.methodData = methodData;
|
||||
}
|
||||
|
||||
static int staticCellCount() {
|
||||
return speculativeTrapCellCount;
|
||||
}
|
||||
|
||||
public int cellCount() {
|
||||
return staticCellCount();
|
||||
}
|
||||
|
||||
public M method() {
|
||||
return methodData.getMethodAtAddress(addressAt(speculativeTrapMethod));
|
||||
}
|
||||
|
||||
static public int methodIndex() {
|
||||
return speculativeTrapMethod;
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
printShared(st, "SpeculativeTrapData");
|
||||
tab(st);
|
||||
methodData.printMethodValueOn(method(), st);
|
||||
st.println();
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// Entries in a ProfileData object to record types: it can either be
|
||||
// none (no profile), unknown (conflicting profile data) or a klass if
|
||||
// a single one is seen. Whether a null reference was seen is also
|
||||
// recorded. No counter is associated with the type and a single type
|
||||
// is tracked (unlike VirtualCallData).
|
||||
public abstract class TypeEntries<K,M> {
|
||||
static final int nullSeen = 1;
|
||||
static final int typeMask = ~nullSeen;
|
||||
static final int typeUnknown = 2;
|
||||
static final int statusBits = nullSeen | typeUnknown;
|
||||
static final int typeKlassMask = ~statusBits;
|
||||
|
||||
final ProfileData pd;
|
||||
final int baseOff;
|
||||
final MethodDataInterface<K,M> methodData;
|
||||
|
||||
boolean wasNullSeen(int index) {
|
||||
int v = pd.intptrAt(index);
|
||||
return (v & nullSeen) != 0;
|
||||
}
|
||||
|
||||
boolean isTypeUnknown(int index) {
|
||||
int v = pd.intptrAt(index);
|
||||
return (v & typeUnknown) != 0;
|
||||
}
|
||||
|
||||
boolean isTypeNone(int index) {
|
||||
int v = pd.intptrAt(index);
|
||||
return (v & typeMask) == 0;
|
||||
}
|
||||
|
||||
K validKlass(int index) {
|
||||
if (!isTypeNone(index) &&
|
||||
!isTypeUnknown(index)) {
|
||||
return methodData.getKlassAtAddress(pd.addressAt(index).andWithMask(typeKlassMask));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void printKlass(PrintStream st, int index) {
|
||||
if (isTypeNone(index)) {
|
||||
st.print("none");
|
||||
} else if (isTypeUnknown(index)) {
|
||||
st.print("unknown");
|
||||
} else {
|
||||
methodData.printKlassValueOn(validKlass(index), st);
|
||||
}
|
||||
if (wasNullSeen(index)) {
|
||||
st.print(" (null seen)");
|
||||
}
|
||||
}
|
||||
|
||||
TypeEntries(MethodDataInterface<K,M> methodData, ProfileData pd, int baseOff) {
|
||||
this.pd = pd;
|
||||
this.baseOff = baseOff;
|
||||
this.methodData = methodData;
|
||||
}
|
||||
|
||||
long intptrAt(int index) {
|
||||
return pd.intptrAt(index);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// Entries to collect type information at a call: contains arguments
|
||||
// (TypeStackSlotEntries), a return type (ReturnTypeEntry) and a
|
||||
// number of cells.
|
||||
public abstract class TypeEntriesAtCall {
|
||||
|
||||
static int stackSlotLocalOffset(int i) {
|
||||
return headerCellCount() + TypeStackSlotEntries.stackSlotLocalOffset(i);
|
||||
}
|
||||
|
||||
static int argumentTypeLocalOffset(int i) {
|
||||
return headerCellCount() + TypeStackSlotEntries.typeLocalOffset(i);
|
||||
}
|
||||
|
||||
static int headerCellCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cellCountLocalOffset() {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// Type entries used for arguments passed at a call and parameters on
|
||||
// method entry. 2 cells per entry: one for the type encoded as in
|
||||
// TypeEntries and one initialized with the stack slot where the
|
||||
// profiled object is to be found so that the interpreter can locate
|
||||
// it quickly.
|
||||
public class TypeStackSlotEntries<K,M> extends TypeEntries<K,M> {
|
||||
static final int stackSlotEntry = 0;
|
||||
static final int typeEntry = 1;
|
||||
static final int perArgCellCount = 2;
|
||||
|
||||
int stackSlotOffset(int i) {
|
||||
return baseOff + stackSlotLocalOffset(i);
|
||||
}
|
||||
|
||||
final int numberOfEntries;
|
||||
|
||||
int typeOffsetInCells(int i) {
|
||||
return baseOff + typeLocalOffset(i);
|
||||
}
|
||||
|
||||
TypeStackSlotEntries(MethodDataInterface<K,M> methodData, ProfileData pd, int baseOff, int nbEntries) {
|
||||
super(methodData, pd, baseOff);
|
||||
numberOfEntries = nbEntries;
|
||||
}
|
||||
|
||||
static int stackSlotLocalOffset(int i) {
|
||||
return i * perArgCellCount + stackSlotEntry;
|
||||
}
|
||||
|
||||
static int typeLocalOffset(int i) {
|
||||
return i * perArgCellCount + typeEntry;
|
||||
}
|
||||
|
||||
int stackSlot(int i) {
|
||||
return pd.uintAt(stackSlotOffset(i));
|
||||
}
|
||||
|
||||
K type(int i) {
|
||||
return validKlass(typeOffsetInCells(i));
|
||||
}
|
||||
|
||||
static int perArgCount() {
|
||||
return perArgCellCount;
|
||||
}
|
||||
|
||||
int typeIndex(int i) {
|
||||
return typeOffsetInCells(i);
|
||||
}
|
||||
|
||||
void printDataOn(PrintStream st) {
|
||||
for (int i = 0; i < numberOfEntries; i++) {
|
||||
pd.tab(st);
|
||||
st.print(i + ": stack(" + stackSlot(i)+ ") ");
|
||||
printKlass(st, typeOffsetInCells(i));
|
||||
st.println();
|
||||
}
|
||||
}
|
||||
}
|
@ -35,9 +35,9 @@ import sun.jvm.hotspot.utilities.*;
|
||||
//
|
||||
// A VirtualCallData is used to access profiling information about a
|
||||
// call. For now, it has nothing more than a ReceiverTypeData.
|
||||
public class VirtualCallData extends ReceiverTypeData {
|
||||
public VirtualCallData(DataLayout layout) {
|
||||
super(layout);
|
||||
public class VirtualCallData<K,M> extends ReceiverTypeData<K,M> {
|
||||
public VirtualCallData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(methodData, layout);
|
||||
//assert(layout.tag() == DataLayout.virtualCallDataTag, "wrong type");
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.oops;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.types.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
// VirtualCallTypeData
|
||||
//
|
||||
// A VirtualCallTypeData is used to access profiling information about
|
||||
// a virtual call for which we collect type information about
|
||||
// arguments and return value.
|
||||
public class VirtualCallTypeData<K,M> extends VirtualCallData implements CallTypeDataInterface<K> {
|
||||
final TypeStackSlotEntries<K,M> args;
|
||||
final ReturnTypeEntry<K,M> ret;
|
||||
|
||||
int cellCountGlobalOffset() {
|
||||
return VirtualCallData.staticCellCount() + TypeEntriesAtCall.cellCountLocalOffset();
|
||||
}
|
||||
|
||||
int cellCountNoHeader() {
|
||||
return uintAt(cellCountGlobalOffset());
|
||||
}
|
||||
|
||||
public VirtualCallTypeData(MethodDataInterface<K,M> methodData, DataLayout layout) {
|
||||
super(methodData, layout);
|
||||
args = new TypeStackSlotEntries<K,M>(methodData, this, VirtualCallData.staticCellCount()+TypeEntriesAtCall.headerCellCount(), numberOfArguments());
|
||||
ret = new ReturnTypeEntry<K,M>(methodData, this, cellCount() - ReturnTypeEntry.staticCellCount());
|
||||
}
|
||||
|
||||
static int staticCellCount() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int cellCount() {
|
||||
return VirtualCallData.staticCellCount() +
|
||||
TypeEntriesAtCall.headerCellCount() +
|
||||
intAt(cellCountGlobalOffset());
|
||||
}
|
||||
|
||||
public int numberOfArguments() {
|
||||
return cellCountNoHeader() / TypeStackSlotEntries.perArgCount();
|
||||
}
|
||||
|
||||
public boolean hasArguments() {
|
||||
return cellCountNoHeader() >= TypeStackSlotEntries.perArgCount();
|
||||
}
|
||||
|
||||
public K argumentType(int i) {
|
||||
return args.type(i);
|
||||
}
|
||||
|
||||
public boolean hasReturn() {
|
||||
return (cellCountNoHeader() % TypeStackSlotEntries.perArgCount()) != 0;
|
||||
}
|
||||
|
||||
public K returnType() {
|
||||
return ret.type();
|
||||
}
|
||||
|
||||
public int argumentTypeIndex(int i) {
|
||||
return args.typeIndex(i);
|
||||
}
|
||||
|
||||
public int returnTypeIndex() {
|
||||
return ret.typeIndex();
|
||||
}
|
||||
|
||||
public void printDataOn(PrintStream st) {
|
||||
super.printDataOn(st);
|
||||
if (hasArguments()) {
|
||||
tab(st);
|
||||
st.print("argument types");
|
||||
args.printDataOn(st);
|
||||
}
|
||||
if (hasReturn()) {
|
||||
tab(st);
|
||||
st.print("return type");
|
||||
ret.printDataOn(st);
|
||||
}
|
||||
}
|
||||
};
|
@ -177,7 +177,7 @@ void ciReceiverTypeData::translate_receiver_data_from(const ProfileData* data) {
|
||||
|
||||
|
||||
void ciTypeStackSlotEntries::translate_type_data_from(const TypeStackSlotEntries* entries) {
|
||||
for (int i = 0; i < _number_of_entries; i++) {
|
||||
for (int i = 0; i < number_of_entries(); i++) {
|
||||
intptr_t k = entries->type(i);
|
||||
TypeStackSlotEntries::set_type(i, translate_klass(k));
|
||||
}
|
||||
@ -242,7 +242,6 @@ ciProfileData* ciMethodData::next_data(ciProfileData* current) {
|
||||
}
|
||||
|
||||
ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) {
|
||||
// bci_to_extra_data(bci) ...
|
||||
DataLayout* dp = data_layout_at(data_size());
|
||||
DataLayout* end = data_layout_at(data_size() + extra_data_size());
|
||||
two_free_slots = false;
|
||||
@ -506,6 +505,63 @@ void ciMethodData::print_impl(outputStream* st) {
|
||||
ciMetadata::print_impl(st);
|
||||
}
|
||||
|
||||
void ciMethodData::dump_replay_data_type_helper(outputStream* out, int round, int& count, ProfileData* pdata, ByteSize offset, ciKlass* k) {
|
||||
if (k != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d %s", (int)(dp_to_di(pdata->dp() + in_bytes(offset)) / sizeof(intptr_t)), k->name()->as_quoted_ascii());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> void ciMethodData::dump_replay_data_receiver_type_helper(outputStream* out, int round, int& count, T* vdata) {
|
||||
for (uint i = 0; i < vdata->row_limit(); i++) {
|
||||
dump_replay_data_type_helper(out, round, count, vdata, vdata->receiver_offset(i), vdata->receiver(i));
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> void ciMethodData::dump_replay_data_call_type_helper(outputStream* out, int round, int& count, T* call_type_data) {
|
||||
if (call_type_data->has_arguments()) {
|
||||
for (int i = 0; i < call_type_data->number_of_arguments(); i++) {
|
||||
dump_replay_data_type_helper(out, round, count, call_type_data, call_type_data->argument_type_offset(i), call_type_data->valid_argument_type(i));
|
||||
}
|
||||
}
|
||||
if (call_type_data->has_return()) {
|
||||
dump_replay_data_type_helper(out, round, count, call_type_data, call_type_data->return_type_offset(), call_type_data->valid_return_type());
|
||||
}
|
||||
}
|
||||
|
||||
void ciMethodData::dump_replay_data_extra_data_helper(outputStream* out, int round, int& count) {
|
||||
DataLayout* dp = data_layout_at(data_size());
|
||||
DataLayout* end = data_layout_at(data_size() + extra_data_size());
|
||||
|
||||
for (;dp < end; dp = MethodData::next_extra(dp)) {
|
||||
switch(dp->tag()) {
|
||||
case DataLayout::no_tag:
|
||||
case DataLayout::arg_info_data_tag:
|
||||
return;
|
||||
case DataLayout::bit_data_tag:
|
||||
break;
|
||||
case DataLayout::speculative_trap_data_tag: {
|
||||
ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp);
|
||||
ciMethod* m = data->method();
|
||||
if (m != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d ", (int)(dp_to_di(((address)dp) + in_bytes(ciSpeculativeTrapData::method_offset())) / sizeof(intptr_t)));
|
||||
m->dump_name_as_ascii(out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fatal(err_msg("bad tag = %d", dp->tag()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ciMethodData::dump_replay_data(outputStream* out) {
|
||||
ResourceMark rm;
|
||||
MethodData* mdo = get_MethodData();
|
||||
@ -527,7 +583,7 @@ void ciMethodData::dump_replay_data(outputStream* out) {
|
||||
}
|
||||
|
||||
// dump the MDO data as raw data
|
||||
int elements = data_size() / sizeof(intptr_t);
|
||||
int elements = (data_size() + extra_data_size()) / sizeof(intptr_t);
|
||||
out->print(" data %d", elements);
|
||||
for (int i = 0; i < elements; i++) {
|
||||
// We could use INTPTR_FORMAT here but that's a zero justified
|
||||
@ -544,37 +600,35 @@ void ciMethodData::dump_replay_data(outputStream* out) {
|
||||
// and emit pairs of offset and klass name so that they can be
|
||||
// reconstructed at runtime. The first round counts the number of
|
||||
// oop references and the second actually emits them.
|
||||
int count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
ciParametersTypeData* parameters = parameters_type_data();
|
||||
for (int count = 0, round = 0; round < 2; round++) {
|
||||
if (round == 1) out->print(" oops %d", count);
|
||||
ProfileData* pdata = first_data();
|
||||
for ( ; is_valid(pdata); pdata = next_data(pdata)) {
|
||||
if (pdata->is_ReceiverTypeData()) {
|
||||
ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata;
|
||||
for (uint i = 0; i < vdata->row_limit(); i++) {
|
||||
ciKlass* k = vdata->receiver(i);
|
||||
if (k != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d %s", (int)(dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t)), k->name()->as_quoted_ascii());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pdata->is_VirtualCallData()) {
|
||||
if (pdata->is_VirtualCallData()) {
|
||||
ciVirtualCallData* vdata = (ciVirtualCallData*)pdata;
|
||||
for (uint i = 0; i < vdata->row_limit(); i++) {
|
||||
ciKlass* k = vdata->receiver(i);
|
||||
if (k != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d %s", (int)(dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t)), k->name()->as_quoted_ascii());
|
||||
}
|
||||
}
|
||||
dump_replay_data_receiver_type_helper<ciVirtualCallData>(out, round, count, vdata);
|
||||
if (pdata->is_VirtualCallTypeData()) {
|
||||
ciVirtualCallTypeData* call_type_data = (ciVirtualCallTypeData*)pdata;
|
||||
dump_replay_data_call_type_helper<ciVirtualCallTypeData>(out, round, count, call_type_data);
|
||||
}
|
||||
} else if (pdata->is_ReceiverTypeData()) {
|
||||
ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata;
|
||||
dump_replay_data_receiver_type_helper<ciReceiverTypeData>(out, round, count, vdata);
|
||||
} else if (pdata->is_CallTypeData()) {
|
||||
ciCallTypeData* call_type_data = (ciCallTypeData*)pdata;
|
||||
dump_replay_data_call_type_helper<ciCallTypeData>(out, round, count, call_type_data);
|
||||
}
|
||||
}
|
||||
if (parameters != NULL) {
|
||||
for (int i = 0; i < parameters->number_of_parameters(); i++) {
|
||||
dump_replay_data_type_helper(out, round, count, parameters, ParametersTypeData::type_offset(i), parameters->valid_parameter_type(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int count = 0, round = 0; round < 2; round++) {
|
||||
if (round == 1) out->print(" methods %d", count);
|
||||
dump_replay_data_extra_data_helper(out, round, count);
|
||||
}
|
||||
out->cr();
|
||||
}
|
||||
@ -586,6 +640,10 @@ void ciMethodData::print() {
|
||||
|
||||
void ciMethodData::print_data_on(outputStream* st) {
|
||||
ResourceMark rm;
|
||||
ciParametersTypeData* parameters = parameters_type_data();
|
||||
if (parameters != NULL) {
|
||||
parameters->print_data_on(st);
|
||||
}
|
||||
ciProfileData* data;
|
||||
for (data = first_data(); is_valid(data); data = next_data(data)) {
|
||||
st->print("%d", dp_to_di(data->dp()));
|
||||
@ -607,6 +665,9 @@ void ciMethodData::print_data_on(outputStream* st) {
|
||||
data = new ciArgInfoData(dp);
|
||||
dp = end; // ArgInfoData is at the end of extra data section.
|
||||
break;
|
||||
case DataLayout::speculative_trap_data_tag:
|
||||
data = new ciSpeculativeTrapData(dp);
|
||||
break;
|
||||
default:
|
||||
fatal(err_msg("unexpected tag %d", dp->tag()));
|
||||
}
|
||||
@ -631,7 +692,7 @@ void ciTypeEntries::print_ciklass(outputStream* st, intptr_t k) {
|
||||
}
|
||||
|
||||
void ciTypeStackSlotEntries::print_data_on(outputStream* st) const {
|
||||
for (int i = 0; i < _number_of_entries; i++) {
|
||||
for (int i = 0; i < number_of_entries(); i++) {
|
||||
_pd->tab(st);
|
||||
st->print("%d: stack (%u) ", i, stack_slot(i));
|
||||
print_ciklass(st, type(i));
|
||||
@ -650,12 +711,12 @@ void ciCallTypeData::print_data_on(outputStream* st, const char* extra) const {
|
||||
print_shared(st, "ciCallTypeData", extra);
|
||||
if (has_arguments()) {
|
||||
tab(st, true);
|
||||
st->print("argument types");
|
||||
st->print_cr("argument types");
|
||||
args()->print_data_on(st);
|
||||
}
|
||||
if (has_return()) {
|
||||
tab(st, true);
|
||||
st->print("return type");
|
||||
st->print_cr("return type");
|
||||
ret()->print_data_on(st);
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class ciArgInfoData;
|
||||
class ciCallTypeData;
|
||||
class ciVirtualCallTypeData;
|
||||
class ciParametersTypeData;
|
||||
class ciSpeculativeTrapData;;
|
||||
class ciSpeculativeTrapData;
|
||||
|
||||
typedef ProfileData ciProfileData;
|
||||
|
||||
@ -175,7 +175,7 @@ public:
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -202,7 +202,7 @@ public:
|
||||
}
|
||||
void translate_receiver_data_from(const ProfileData* data);
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
void print_receiver_data_on(outputStream* st) const;
|
||||
#endif
|
||||
};
|
||||
@ -227,7 +227,7 @@ public:
|
||||
rtd_super()->translate_receiver_data_from(data);
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -289,7 +289,7 @@ public:
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -338,7 +338,7 @@ public:
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -349,15 +349,15 @@ public:
|
||||
virtual void translate_from(const ProfileData* data);
|
||||
|
||||
ciMethod* method() const {
|
||||
return (ciMethod*)intptr_at(method_offset);
|
||||
return (ciMethod*)intptr_at(speculative_trap_method);
|
||||
}
|
||||
|
||||
void set_method(ciMethod* m) {
|
||||
set_intptr_at(method_offset, (intptr_t)m);
|
||||
set_intptr_at(speculative_trap_method, (intptr_t)m);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_data_on(outputStream* st, const char* extra) const;
|
||||
void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -406,8 +406,8 @@ private:
|
||||
// Coherent snapshot of original header.
|
||||
MethodData _orig;
|
||||
|
||||
// Dedicated area dedicated to parameters. Null if no parameter
|
||||
// profiling for this method.
|
||||
// Area dedicated to parameters. NULL if no parameter profiling for
|
||||
// this method.
|
||||
DataLayout* _parameters;
|
||||
|
||||
ciMethodData(MethodData* md);
|
||||
@ -467,6 +467,11 @@ private:
|
||||
void load_extra_data();
|
||||
ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots);
|
||||
|
||||
void dump_replay_data_type_helper(outputStream* out, int round, int& count, ProfileData* pdata, ByteSize offset, ciKlass* k);
|
||||
template<class T> void dump_replay_data_call_type_helper(outputStream* out, int round, int& count, T* call_type_data);
|
||||
template<class T> void dump_replay_data_receiver_type_helper(outputStream* out, int round, int& count, T* call_type_data);
|
||||
void dump_replay_data_extra_data_helper(outputStream* out, int round, int& count);
|
||||
|
||||
public:
|
||||
bool is_method_data() const { return true; }
|
||||
|
||||
|
@ -48,11 +48,14 @@ typedef struct _ciMethodDataRecord {
|
||||
|
||||
intptr_t* _data;
|
||||
char* _orig_data;
|
||||
jobject* _oops_handles;
|
||||
int* _oops_offsets;
|
||||
Klass** _classes;
|
||||
Method** _methods;
|
||||
int* _classes_offsets;
|
||||
int* _methods_offsets;
|
||||
int _data_length;
|
||||
int _orig_data_length;
|
||||
int _oops_length;
|
||||
int _classes_length;
|
||||
int _methods_length;
|
||||
} ciMethodDataRecord;
|
||||
|
||||
typedef struct _ciMethodRecord {
|
||||
@ -565,7 +568,7 @@ class CompileReplay : public StackObj {
|
||||
rec->_instructions_size = parse_int("instructions_size");
|
||||
}
|
||||
|
||||
// ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length>
|
||||
// ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length> # ... methods <length>
|
||||
void process_ciMethodData(TRAPS) {
|
||||
Method* method = parse_method(CHECK);
|
||||
if (had_error()) return;
|
||||
@ -602,21 +605,34 @@ class CompileReplay : public StackObj {
|
||||
if (rec->_data == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!parse_tag_and_count("oops", rec->_oops_length)) {
|
||||
if (!parse_tag_and_count("oops", rec->_classes_length)) {
|
||||
return;
|
||||
}
|
||||
rec->_oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->_oops_length);
|
||||
rec->_oops_offsets = NEW_RESOURCE_ARRAY(int, rec->_oops_length);
|
||||
for (int i = 0; i < rec->_oops_length; i++) {
|
||||
rec->_classes = NEW_RESOURCE_ARRAY(Klass*, rec->_classes_length);
|
||||
rec->_classes_offsets = NEW_RESOURCE_ARRAY(int, rec->_classes_length);
|
||||
for (int i = 0; i < rec->_classes_length; i++) {
|
||||
int offset = parse_int("offset");
|
||||
if (had_error()) {
|
||||
return;
|
||||
}
|
||||
Klass* k = parse_klass(CHECK);
|
||||
rec->_oops_offsets[i] = offset;
|
||||
KlassHandle *kh = NEW_C_HEAP_OBJ(KlassHandle, mtCompiler);
|
||||
::new ((void*)kh) KlassHandle(THREAD, k);
|
||||
rec->_oops_handles[i] = (jobject)kh;
|
||||
rec->_classes_offsets[i] = offset;
|
||||
rec->_classes[i] = k;
|
||||
}
|
||||
|
||||
if (!parse_tag_and_count("methods", rec->_methods_length)) {
|
||||
return;
|
||||
}
|
||||
rec->_methods = NEW_RESOURCE_ARRAY(Method*, rec->_methods_length);
|
||||
rec->_methods_offsets = NEW_RESOURCE_ARRAY(int, rec->_methods_length);
|
||||
for (int i = 0; i < rec->_methods_length; i++) {
|
||||
int offset = parse_int("offset");
|
||||
if (had_error()) {
|
||||
return;
|
||||
}
|
||||
Method* m = parse_method(CHECK);
|
||||
rec->_methods_offsets[i] = offset;
|
||||
rec->_methods[i] = m;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1105,14 +1121,22 @@ void ciReplay::initialize(ciMethodData* m) {
|
||||
m->_state = rec->_state;
|
||||
m->_current_mileage = rec->_current_mileage;
|
||||
if (rec->_data_length != 0) {
|
||||
assert(m->_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree");
|
||||
assert(m->_data_size + m->_extra_data_size == rec->_data_length * (int)sizeof(rec->_data[0]) ||
|
||||
m->_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree");
|
||||
|
||||
// Write the correct ciObjects back into the profile data
|
||||
ciEnv* env = ciEnv::current();
|
||||
for (int i = 0; i < rec->_oops_length; i++) {
|
||||
KlassHandle *h = (KlassHandle *)rec->_oops_handles[i];
|
||||
*(ciMetadata**)(rec->_data + rec->_oops_offsets[i]) =
|
||||
env->get_metadata((*h)());
|
||||
for (int i = 0; i < rec->_classes_length; i++) {
|
||||
Klass *k = rec->_classes[i];
|
||||
// In case this class pointer is is tagged, preserve the tag
|
||||
// bits
|
||||
rec->_data[rec->_classes_offsets[i]] =
|
||||
ciTypeEntries::with_status(env->get_metadata(k)->as_klass(), rec->_data[rec->_classes_offsets[i]]);
|
||||
}
|
||||
for (int i = 0; i < rec->_methods_length; i++) {
|
||||
Method *m = rec->_methods[i];
|
||||
*(ciMetadata**)(rec->_data + rec->_methods_offsets[i]) =
|
||||
env->get_metadata(m);
|
||||
}
|
||||
// Copy the updated profile data into place as intptr_ts
|
||||
#ifdef _LP64
|
||||
|
@ -851,11 +851,10 @@ private:
|
||||
return _base_off + stack_slot_local_offset(i);
|
||||
}
|
||||
|
||||
protected:
|
||||
const int _number_of_entries;
|
||||
|
||||
// offset of cell for type for entry i within ProfileData object
|
||||
int type_offset(int i) const {
|
||||
int type_offset_in_cells(int i) const {
|
||||
return _base_off + type_local_offset(i);
|
||||
}
|
||||
|
||||
@ -868,6 +867,8 @@ public:
|
||||
|
||||
void post_initialize(Symbol* signature, bool has_receiver, bool include_receiver);
|
||||
|
||||
int number_of_entries() const { return _number_of_entries; }
|
||||
|
||||
// offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries
|
||||
static int stack_slot_local_offset(int i) {
|
||||
return i * per_arg_cell_count + stack_slot_entry;
|
||||
@ -893,13 +894,13 @@ public:
|
||||
// type for entry i
|
||||
intptr_t type(int i) const {
|
||||
assert(i >= 0 && i < _number_of_entries, "oob");
|
||||
return _pd->intptr_at(type_offset(i));
|
||||
return _pd->intptr_at(type_offset_in_cells(i));
|
||||
}
|
||||
|
||||
// set type for entry i
|
||||
void set_type(int i, intptr_t k) {
|
||||
assert(i >= 0 && i < _number_of_entries, "oob");
|
||||
_pd->set_intptr_at(type_offset(i), k);
|
||||
_pd->set_intptr_at(type_offset_in_cells(i), k);
|
||||
}
|
||||
|
||||
static ByteSize per_arg_size() {
|
||||
@ -907,7 +908,11 @@ public:
|
||||
}
|
||||
|
||||
static int per_arg_count() {
|
||||
return per_arg_cell_count ;
|
||||
return per_arg_cell_count;
|
||||
}
|
||||
|
||||
ByteSize type_offset(int i) const {
|
||||
return DataLayout::cell_offset(type_offset_in_cells(i));
|
||||
}
|
||||
|
||||
// GC support
|
||||
@ -973,7 +978,7 @@ private:
|
||||
}
|
||||
|
||||
static int argument_type_local_offset(int i) {
|
||||
return header_cell_count() + TypeStackSlotEntries::type_local_offset(i);;
|
||||
return header_cell_count() + TypeStackSlotEntries::type_local_offset(i);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1129,6 +1134,14 @@ public:
|
||||
return cell_offset(CounterData::static_cell_count()) + TypeEntriesAtCall::args_data_offset();
|
||||
}
|
||||
|
||||
ByteSize argument_type_offset(int i) {
|
||||
return _args.type_offset(i);
|
||||
}
|
||||
|
||||
ByteSize return_type_offset() {
|
||||
return _ret.type_offset();
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
|
||||
if (has_arguments()) {
|
||||
@ -1436,6 +1449,14 @@ public:
|
||||
return cell_offset(VirtualCallData::static_cell_count()) + TypeEntriesAtCall::args_data_offset();
|
||||
}
|
||||
|
||||
ByteSize argument_type_offset(int i) {
|
||||
return _args.type_offset(i);
|
||||
}
|
||||
|
||||
ByteSize return_type_offset() {
|
||||
return _ret.type_offset();
|
||||
}
|
||||
|
||||
// GC support
|
||||
virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
|
||||
ReceiverTypeData::clean_weak_klass_links(is_alive_closure);
|
||||
@ -1926,7 +1947,7 @@ public:
|
||||
class SpeculativeTrapData : public ProfileData {
|
||||
protected:
|
||||
enum {
|
||||
method_offset,
|
||||
speculative_trap_method,
|
||||
speculative_trap_cell_count
|
||||
};
|
||||
public:
|
||||
@ -1946,11 +1967,15 @@ public:
|
||||
|
||||
// Direct accessor
|
||||
Method* method() const {
|
||||
return (Method*)intptr_at(method_offset);
|
||||
return (Method*)intptr_at(speculative_trap_method);
|
||||
}
|
||||
|
||||
void set_method(Method* m) {
|
||||
set_intptr_at(method_offset, (intptr_t)m);
|
||||
set_intptr_at(speculative_trap_method, (intptr_t)m);
|
||||
}
|
||||
|
||||
static ByteSize method_offset() {
|
||||
return cell_offset(speculative_trap_method);
|
||||
}
|
||||
|
||||
virtual void print_data_on(outputStream* st, const char* extra = NULL) const;
|
||||
|
@ -353,6 +353,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
nonstatic_field(MethodData, _method, Method*) \
|
||||
nonstatic_field(MethodData, _data_size, int) \
|
||||
nonstatic_field(MethodData, _data[0], intptr_t) \
|
||||
nonstatic_field(MethodData, _parameters_type_data_di, int) \
|
||||
nonstatic_field(MethodData, _nof_decompiles, uint) \
|
||||
nonstatic_field(MethodData, _nof_overflow_recompiles, uint) \
|
||||
nonstatic_field(MethodData, _nof_overflow_traps, uint) \
|
||||
@ -2499,6 +2500,10 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
declare_constant(Deoptimization::Reason_age) \
|
||||
declare_constant(Deoptimization::Reason_predicate) \
|
||||
declare_constant(Deoptimization::Reason_loop_limit_check) \
|
||||
declare_constant(Deoptimization::Reason_speculate_class_check) \
|
||||
declare_constant(Deoptimization::Reason_speculate_null_check) \
|
||||
declare_constant(Deoptimization::Reason_rtm_state_change) \
|
||||
declare_constant(Deoptimization::Reason_tenured) \
|
||||
declare_constant(Deoptimization::Reason_LIMIT) \
|
||||
declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \
|
||||
\
|
||||
|
Loading…
x
Reference in New Issue
Block a user