< prev index next >
src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiledClass.java
Print this page
rev 47466 : 8132547: [AOT] support invokedynamic instructions
Reviewed-by: iveresov, kvn
*** 23,80 ****
package jdk.tools.jaotc;
import java.util.ArrayList;
import java.util.HashMap;
! import java.util.Map;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
/**
* Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
* of a class {@code className} are maintained in an array list.
*/
final class AOTCompiledClass {
static class AOTKlassData {
private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
private int classId; // Unique ID
// Offset to compiled methods data in the .methods.offsets section.
private int compiledMethodsOffset;
// Offset to dependent methods data.
private int dependentMethodsOffset;
- private long fingerprint; // Class fingerprint
! private final String name;
! private boolean isArray;
/**
* List of dependent compiled methods which have a reference to this class.
*/
private ArrayList<CompiledMethodInfo> dependentMethods;
! AOTKlassData(BinaryContainer binaryContainer, String name, long fingerprint, int classId) {
this.dependentMethods = new ArrayList<>();
this.classId = classId;
! this.fingerprint = fingerprint;
! this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(name);
this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
this.dependentMethodsOffset = -1;
- this.name = name;
- this.isArray = name.length() > 0 && name.charAt(0) == '[';
}
! long getFingerprint() {
! return fingerprint;
}
/**
* Add a method to the list of dependent methods.
*/
--- 23,126 ----
package jdk.tools.jaotc;
import java.util.ArrayList;
import java.util.HashMap;
! import java.util.Set;
import jdk.tools.jaotc.binformat.BinaryContainer;
import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
import jdk.tools.jaotc.binformat.Symbol.Binding;
import jdk.tools.jaotc.binformat.Symbol.Kind;
+ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
+ import jdk.tools.jaotc.AOTDynamicTypeStore.AdapterLocation;
+ import jdk.tools.jaotc.AOTDynamicTypeStore.AppendixLocation;
+ import jdk.tools.jaotc.AOTDynamicTypeStore.Location;
+
/**
* Class encapsulating Graal-compiled output of a Java class. The compilation result of all methods
* of a class {@code className} are maintained in an array list.
*/
final class AOTCompiledClass {
+ private static AOTDynamicTypeStore dynoStore;
+
+ static void setDynamicTypeStore(AOTDynamicTypeStore s) {
+ dynoStore = s;
+ }
+
static class AOTKlassData {
private int gotIndex; // Index (offset/8) to the got in the .metaspace.got section
private int classId; // Unique ID
// Offset to compiled methods data in the .methods.offsets section.
private int compiledMethodsOffset;
// Offset to dependent methods data.
private int dependentMethodsOffset;
! private final String metadataName;
! HotSpotResolvedObjectType type;
/**
* List of dependent compiled methods which have a reference to this class.
*/
private ArrayList<CompiledMethodInfo> dependentMethods;
! AOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type, int classId) {
this.dependentMethods = new ArrayList<>();
this.classId = classId;
! this.type = type;
! this.metadataName = type.isAnonymous() ? "anon<"+ classId + ">": type.getName();
! this.gotIndex = binaryContainer.addTwoSlotKlassSymbol(metadataName);
this.compiledMethodsOffset = -1; // Not compiled classes do not have compiled methods.
this.dependentMethodsOffset = -1;
}
! private String[] getMetaspaceNames() {
! String name = metadataName;
! Set<Location> locs = dynoStore.getDynamicClassLocationsForType(type);
! if (locs == null) {
! return new String[] {name};
! } else {
! ArrayList<String> names = new ArrayList<String>();
! names.add(name);
! for (Location l : locs) {
! HotSpotResolvedObjectType cpType = l.getHolder();
! AOTKlassData data = getAOTKlassData(cpType);
! // We collect dynamic types at parse time, but late inlining
! // may record types that don't make it into the final graph.
! // We can safely ignore those here.
! if (data == null) {
! // Not a compiled or inlined method
! continue;
! }
! int cpi = l.getCpi();
! String location = "<"+ data.classId + ":" + cpi + ">";
! if (l instanceof AdapterLocation) {
! names.add("adapter" + location);
! AdapterLocation a = (AdapterLocation)l;
! names.add("adapter:" + a.getMethodId() + location);
! } else {
! assert l instanceof AppendixLocation;
! names.add("appendix" + location);
! }
! }
! return names.toArray(new String[names.size()]);
! }
! }
!
! HotSpotResolvedObjectType getType() {
! return type;
! }
!
! String getMetadataName() {
! return metadataName;
}
/**
* Add a method to the list of dependent methods.
*/
*** 110,143 ****
ReadOnlyDataContainer dependenciesContainer = binaryContainer.getKlassesDependenciesContainer();
this.dependentMethodsOffset = BinaryContainer.addMethodsCount(cntDepMethods, dependenciesContainer);
for (CompiledMethodInfo methodInfo : dependentMethods) {
dependenciesContainer.appendInt(methodInfo.getCodeId());
}
verify();
// @formatter:off
/*
* The offsets layout should match AOTKlassData structure in AOT JVM runtime
*/
int offset = container.getByteStreamSize();
container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
// Add index (offset/8) to the got in the .metaspace.got section
container.appendInt(gotIndex).
// Add unique ID
appendInt(classId).
// Add the offset to compiled methods data in the .metaspace.offsets section.
appendInt(compiledMethodsOffset).
// Add the offset to dependent methods data in the .metaspace.offsets section.
appendInt(dependentMethodsOffset).
// Add fingerprint.
! appendLong(fingerprint);
// @formatter:on
}
private void verify() {
assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
! assert isArray || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
assert compiledMethodsOffset >= -1 : "incorrect compiledMethodsOffset: " + compiledMethodsOffset + " for klass: " + name;
assert dependentMethodsOffset >= -1 : "incorrect dependentMethodsOffset: " + dependentMethodsOffset + " for klass: " + name;
assert classId >= 0 : "incorrect classId: " + classId + " for klass: " + name;
}
--- 156,195 ----
ReadOnlyDataContainer dependenciesContainer = binaryContainer.getKlassesDependenciesContainer();
this.dependentMethodsOffset = BinaryContainer.addMethodsCount(cntDepMethods, dependenciesContainer);
for (CompiledMethodInfo methodInfo : dependentMethods) {
dependenciesContainer.appendInt(methodInfo.getCodeId());
}
+
verify();
// @formatter:off
/*
* The offsets layout should match AOTKlassData structure in AOT JVM runtime
*/
int offset = container.getByteStreamSize();
+ for (String name : getMetaspaceNames()) {
container.createSymbol(offset, Kind.OBJECT, Binding.GLOBAL, 0, name);
+ }
// Add index (offset/8) to the got in the .metaspace.got section
container.appendInt(gotIndex).
// Add unique ID
appendInt(classId).
// Add the offset to compiled methods data in the .metaspace.offsets section.
appendInt(compiledMethodsOffset).
// Add the offset to dependent methods data in the .metaspace.offsets section.
appendInt(dependentMethodsOffset).
// Add fingerprint.
! appendLong(type.getFingerprint());
!
// @formatter:on
}
private void verify() {
+ String name = type.getName();
assert gotIndex > 0 : "incorrect gotIndex: " + gotIndex + " for klass: " + name;
! long fingerprint = type.getFingerprint();
! assert type.isArray() || fingerprint != 0 : "incorrect fingerprint: " + fingerprint + " for klass: " + name;
assert compiledMethodsOffset >= -1 : "incorrect compiledMethodsOffset: " + compiledMethodsOffset + " for klass: " + name;
assert dependentMethodsOffset >= -1 : "incorrect dependentMethodsOffset: " + dependentMethodsOffset + " for klass: " + name;
assert classId >= 0 : "incorrect classId: " + classId + " for klass: " + name;
}
*** 146,156 ****
private final HotSpotResolvedObjectType resolvedJavaType;
/**
* List of all collected class data.
*/
! private static Map<String, AOTKlassData> klassData = new HashMap<>();
/**
* List of all methods to be compiled.
*/
private ArrayList<ResolvedJavaMethod> methods = new ArrayList<>();
--- 198,208 ----
private final HotSpotResolvedObjectType resolvedJavaType;
/**
* List of all collected class data.
*/
! private static HashMap<String, AOTKlassData> klassData = new HashMap<>();
/**
* List of all methods to be compiled.
*/
private ArrayList<ResolvedJavaMethod> methods = new ArrayList<>();
*** 267,293 ****
/**
* Add a klass data.
*/
synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
String name = type.getName();
- long fingerprint = type.getFingerprint();
AOTKlassData data = klassData.get(name);
if (data != null) {
! assert data.getFingerprint() == fingerprint : "incorrect fingerprint data for klass: " + name;
} else {
! data = new AOTKlassData(binaryContainer, name, fingerprint, classesCount++);
klassData.put(name, data);
}
return data;
}
! synchronized static AOTKlassData getAOTKlassData(String name) {
return klassData.get(name);
}
synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
! return getAOTKlassData(type.getName());
}
void addAOTKlassData(BinaryContainer binaryContainer) {
for (CompiledMethodInfo methodInfo : compiledMethods) {
// Record methods holder
--- 319,347 ----
/**
* Add a klass data.
*/
synchronized static AOTKlassData addAOTKlassData(BinaryContainer binaryContainer, HotSpotResolvedObjectType type) {
String name = type.getName();
AOTKlassData data = klassData.get(name);
if (data != null) {
! assert data.getType() == type : "duplicate classes for name " + name;
} else {
! data = new AOTKlassData(binaryContainer, type, classesCount++);
klassData.put(name, data);
}
return data;
}
! private synchronized static AOTKlassData getAOTKlassData(String name) {
return klassData.get(name);
}
synchronized static AOTKlassData getAOTKlassData(HotSpotResolvedObjectType type) {
! String name = type.getName();
! AOTKlassData data = getAOTKlassData(name);
! assert data == null || data.getType() == type : "duplicate classes for name " + name;
! return data;
}
void addAOTKlassData(BinaryContainer binaryContainer) {
for (CompiledMethodInfo methodInfo : compiledMethods) {
// Record methods holder
*** 352,376 ****
int startMethods = BinaryContainer.addMethodsCount(cntMethods, container);
for (CompiledMethodInfo methodInfo : compiledMethods) {
methodInfo.addMethodOffsets(binaryContainer, container);
}
String name = resolvedJavaType.getName();
! AOTKlassData data = klassData.get(name);
assert data != null : "missing data for klass: " + name;
- assert data.getFingerprint() == resolvedJavaType.getFingerprint() : "incorrect fingerprint for klass: " + name;
int cntDepMethods = data.dependentMethods.size();
assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
data.setCompiledMethodsOffset(startMethods);
}
static void putAOTKlassData(BinaryContainer binaryContainer) {
ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
for (AOTKlassData data : klassData.values()) {
data.putAOTKlassData(binaryContainer, container);
}
}
boolean representsStubs() {
return representsStubs;
}
void clear() {
--- 406,464 ----
int startMethods = BinaryContainer.addMethodsCount(cntMethods, container);
for (CompiledMethodInfo methodInfo : compiledMethods) {
methodInfo.addMethodOffsets(binaryContainer, container);
}
String name = resolvedJavaType.getName();
! AOTKlassData data = getAOTKlassData(resolvedJavaType);
assert data != null : "missing data for klass: " + name;
int cntDepMethods = data.dependentMethods.size();
assert cntDepMethods > 0 : "no dependent methods for compiled klass: " + name;
data.setCompiledMethodsOffset(startMethods);
}
static void putAOTKlassData(BinaryContainer binaryContainer) {
+ // record dynamic types
+ Set<HotSpotResolvedObjectType> dynoTypes = dynoStore.getDynamicTypes();
+ if (dynoTypes != null) {
+ for (HotSpotResolvedObjectType dynoType : dynoTypes) {
+ addFingerprintKlassData(binaryContainer, dynoType);
+ }
+ }
+
ReadOnlyDataContainer container = binaryContainer.getKlassesOffsetsContainer();
for (AOTKlassData data : klassData.values()) {
data.putAOTKlassData(binaryContainer, container);
}
}
+ static HotSpotResolvedObjectType getType(Object ref) {
+ return (ref instanceof HotSpotResolvedObjectType) ?
+ (HotSpotResolvedObjectType)ref :
+ ((HotSpotResolvedJavaMethod)ref).getDeclaringClass();
+ }
+
+ static String metadataName(HotSpotResolvedObjectType type) {
+ AOTKlassData data = getAOTKlassData(type);
+ assert data != null : "no data for " + type;
+ return getAOTKlassData(type).getMetadataName();
+ }
+
+ private static String metadataName(HotSpotResolvedJavaMethod m) {
+ return metadataName(m.getDeclaringClass()) + "." + m.getName() + m.getSignature().toMethodDescriptor();
+ }
+
+ static String metadataName(Object ref) {
+ if (ref instanceof HotSpotResolvedJavaMethod) {
+ HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod)ref;
+ return metadataName(m);
+ } else {
+ assert ref instanceof HotSpotResolvedObjectType : "unexpected object type " + ref.getClass().getName();
+ HotSpotResolvedObjectType type = (HotSpotResolvedObjectType)ref;
+ return metadataName(type);
+ }
+ }
+
boolean representsStubs() {
return representsStubs;
}
void clear() {
< prev index next >