提交 cd0cd855 编写于 作者: R roland

8026694: New type profiling points break compilation replay

Summary: fixes compilation replay with new profiling points
Reviewed-by: kvn, twisti
上级 3de5136c
......@@ -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,31 +330,29 @@ 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();
}
}
/*
* 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);
}
int numberOfArgs() {
return arrayLen();
}
public Klass receiver(int row) {
throw new InternalError("should not call");
int argModified(int arg) {
return arrayUintAt(arg);
}
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);
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();
}
}
/*
* 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);
}
}
}
/*
* 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();
}
......
/*
* 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);
}
/*
* 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) + ")");
}
}
......
/*
* 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);
}
K type() {
return validKlass(baseOff);
}
public Klass receiver(int row) {
throw new InternalError("should not call");
static int staticCellCount() {
return cellCount;
}
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;
int typeIndex() {
return baseOff;
}
void printDataOn(PrintStream st) {
pd.tab(st);
printKlass(st, baseOff);
st.println();
}
}
/*
* 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();
}
}
/*
* 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);
}
}
/*
* 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;
}
}
/*
* 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");
}
......
/*
* 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,38 +600,36 @@ 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) \
\
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册