Skip to content

Commit 85207da

Browse files
Setup type and dispatch data for crema dynamic hubs
* Setup type id * Setup open world type check slots * Setup dispatch tables (v&i-tables) * Setup layout encoding, identity hash & monitor offsets * Use unnamed module until modules are supported in crema Co-Authored-By: Thomas Garcia <[email protected]>
1 parent 8867b8e commit 85207da

27 files changed

+1417
-146
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/CremaSupport.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,33 @@
2424
*/
2525
package com.oracle.svm.core.hub;
2626

27+
import java.util.List;
28+
29+
import org.graalvm.nativeimage.ImageSingletons;
2730
import org.graalvm.nativeimage.Platform;
2831
import org.graalvm.nativeimage.Platforms;
2932

33+
import com.oracle.svm.espresso.classfile.ParserKlass;
34+
3035
import jdk.vm.ci.meta.ResolvedJavaType;
3136

3237
public interface CremaSupport {
3338
@Platforms(Platform.HOSTED_ONLY.class)
3439
ResolvedJavaType createInterpreterType(DynamicHub hub, ResolvedJavaType analysisType);
40+
41+
int getAfterFieldsOffset(DynamicHub hub);
42+
43+
interface CremaDispatchTable {
44+
int vtableLength();
45+
46+
int itableLength(Class<?> iface);
47+
}
48+
49+
CremaDispatchTable getDispatchTable(ParserKlass parsed, Class<?> superClass, List<Class<?>> superInterfaces);
50+
51+
void fillDynamicHubInfo(DynamicHub hub, CremaDispatchTable table, List<Class<?>> transitiveSuperInterfaces, int[] interfaceIndices);
52+
53+
static CremaSupport singleton() {
54+
return ImageSingletons.lookup(CremaSupport.class);
55+
}
3556
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
import jdk.internal.reflect.FieldAccessor;
154154
import jdk.internal.reflect.Reflection;
155155
import jdk.internal.reflect.ReflectionFactory;
156+
import jdk.vm.ci.meta.JavaKind;
156157
import jdk.vm.ci.meta.ResolvedJavaType;
157158
import sun.reflect.annotation.AnnotationType;
158159
import sun.reflect.generics.factory.GenericsFactory;
@@ -432,47 +433,92 @@ public DynamicHub(Class<?> hostedJavaClass, String name, byte hubType, Reference
432433
*/
433434
@NeverInline("Fields of DynamicHub are immutable. Immutable reads could float above ANY_LOCATION writes.")
434435
public static DynamicHub allocate(String name, DynamicHub superHub, Object interfacesEncoding, DynamicHub componentHub, String sourceFileName,
435-
int modifiers, short flags, ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName,
436-
Object declaringClass, String signature) {
436+
int modifiers, short flags, ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Module module,
437+
Object declaringClass, String signature, int typeID,
438+
short numClassTypes,
439+
short typeIDDepth,
440+
short numInterfacesTypes,
441+
int[] openTypeWorldTypeCheckSlots, int vTableEntries,
442+
int afterFieldsOffset, boolean valueBased) {
437443
VMError.guarantee(RuntimeClassLoading.isSupported());
438444

439445
ReferenceType referenceType = ReferenceType.computeReferenceType(DynamicHub.toClass(superHub));
440-
// GR-59683: HubType.OBJECT_ARRAY?
441-
byte hubType = HubType.INSTANCE;
442-
if (referenceType != ReferenceType.None) {
443-
hubType = HubType.REFERENCE_INSTANCE;
446+
byte hubType;
447+
if (componentHub != null) {
448+
if (componentHub.isPrimitive()) {
449+
hubType = HubType.PRIMITIVE_ARRAY;
450+
} else {
451+
hubType = HubType.OBJECT_ARRAY;
452+
}
453+
} else {
454+
if (referenceType == ReferenceType.None) {
455+
hubType = HubType.INSTANCE;
456+
} else {
457+
hubType = HubType.REFERENCE_INSTANCE;
458+
}
444459
}
445460

446-
// GR-62339
447-
Module module = null;
448-
449-
// GR-59683: Setup interpreter metadata at run-time.
450-
ResolvedJavaType interpreterType = null;
451-
452-
DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature,
453-
interpreterType);
461+
DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
454462

455463
/* Always allow unsafe allocation for classes that were loaded at run-time. */
456464
companion.canUnsafeAllocate = true;
457465

458-
// GR-59687: Correct size and content for vtable
459-
int vTableEntries = 0x100;
460466
companion.classInitializationInfo = new ClassInitializationInfo(false);
461467

462-
// GR-60069: Determine size for instance and offsets for monitor and identityHashCode
463-
int layoutEncoding = 0x40;
464-
char monitorOffset = 0;
465-
char identityHashOffset = 0;
468+
assert !isFlagSet(flags, IS_PRIMITIVE_FLAG_BIT);
469+
boolean isInterface = isFlagSet(flags, IS_INTERFACE_FLAG_BIT);
470+
int layoutEncoding;
471+
int monitorOffset = 0;
472+
int identityHashOffset = 0;
473+
474+
// See also similar logic in UniverseBuilder.buildHubs
475+
ObjectLayout ol = ConfigurationValues.getObjectLayout();
476+
if (componentHub != null) {
477+
// array
478+
JavaKind componentKind = JavaKind.fromJavaClass(DynamicHub.toClass(componentHub));
479+
boolean isObject = (componentKind == JavaKind.Object);
480+
layoutEncoding = LayoutEncoding.forArray(isObject, ol.getArrayBaseOffset(componentKind), ol.getArrayIndexShift(componentKind));
481+
if (ol.isIdentityHashFieldInObjectHeader() || ol.isIdentityHashFieldAtTypeSpecificOffset()) {
482+
identityHashOffset = NumUtil.safeToInt(ol.getObjectHeaderIdentityHashOffset());
483+
}
484+
} else if (isInterface) {
485+
layoutEncoding = LayoutEncoding.forInterface();
486+
} else {
487+
// instance class
488+
assert !"java.lang.Class".equals(name);
489+
// @Hybrid is ignored
490+
if (Modifier.isAbstract(modifiers)) {
491+
layoutEncoding = LayoutEncoding.forAbstract();
492+
} else {
493+
int instanceSize = afterFieldsOffset;
494+
495+
boolean needsMonitorOffset = !valueBased;
496+
if (needsMonitorOffset) {
497+
// GR-60069 could look for gaps
498+
int size = ol.getReferenceSize();
499+
int bits = size - 1;
500+
int alignmentAdjust = ((instanceSize + bits) & ~bits) - instanceSize;
501+
monitorOffset = instanceSize + alignmentAdjust;
502+
instanceSize = monitorOffset + size;
503+
}
466504

467-
// GR-59687: Determine typecheck related infos
468-
int typeID = 0;
469-
short typeIDDepth = 0;
470-
short numClassTypes = 2;
471-
short numInterfacesTypes = 0;
472-
int[] openTypeWorldTypeCheckSlots = new int[numClassTypes + (numInterfacesTypes * 2)];
505+
if (ol.isIdentityHashFieldInObjectHeader()) {
506+
identityHashOffset = ol.getObjectHeaderIdentityHashOffset();
507+
} else if (ol.isIdentityHashFieldAtTypeSpecificOffset() || ol.isIdentityHashFieldOptional()) {
508+
// GR-60069 could look for gaps
509+
int bits = Integer.BYTES - 1;
510+
int alignmentAdjust = ((instanceSize + bits) & ~bits) - instanceSize;
511+
identityHashOffset = instanceSize + alignmentAdjust;
512+
instanceSize = identityHashOffset + Integer.BYTES;
513+
} else {
514+
throw VMError.shouldNotReachHere("Unexpected identity hash mode");
515+
}
516+
layoutEncoding = LayoutEncoding.forPureInstance(ol.alignUp(instanceSize));
517+
}
518+
}
473519

474520
companion.interfacesEncoding = interfacesEncoding;
475-
// GR-59683: Proper value needed.
521+
// GR-57813: setup a LazyFinalReference that calls `values` via reflection.
476522
companion.enumConstantsReference = null;
477523

478524
/*
@@ -519,8 +565,10 @@ public static DynamicHub allocate(String name, DynamicHub superHub, Object inter
519565
writeShort(hub, dynamicHubOffsets.getNumInterfaceTypesOffset(), numInterfacesTypes);
520566
writeObject(hub, dynamicHubOffsets.getOpenTypeWorldTypeCheckSlotsOffset(), openTypeWorldTypeCheckSlots);
521567

522-
writeChar(hub, dynamicHubOffsets.getMonitorOffsetOffset(), monitorOffset);
523-
writeChar(hub, dynamicHubOffsets.getIdentityHashOffsetOffset(), identityHashOffset);
568+
VMError.guarantee(monitorOffset == (char) monitorOffset);
569+
VMError.guarantee(identityHashOffset == (char) identityHashOffset);
570+
writeChar(hub, dynamicHubOffsets.getMonitorOffsetOffset(), (char) monitorOffset);
571+
writeChar(hub, dynamicHubOffsets.getIdentityHashOffsetOffset(), (char) identityHashOffset);
524572

525573
writeShort(hub, dynamicHubOffsets.getFlagsOffset(), flags);
526574

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,17 @@ public final class DynamicHubCompanion {
149149
static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
150150
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
151151

152-
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature, null);
152+
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
153153
}
154154

155155
static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
156-
ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature,
157-
ResolvedJavaType interpreterType) {
156+
ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
158157
assert RuntimeClassLoading.isSupported();
159-
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature, interpreterType);
158+
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
160159
}
161160

162161
private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
163-
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature, ResolvedJavaType interpreterType) {
162+
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
164163
this.module = module;
165164
this.superHub = superHub;
166165
this.sourceFileName = sourceFileName;
@@ -171,6 +170,5 @@ private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFil
171170
this.signature = signature;
172171

173172
this.classLoader = classLoader;
174-
this.interpreterType = interpreterType;
175173
}
176174
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ private static void guaranteeEncoding(ResolvedJavaType type, boolean expected, b
118118
@Platforms(Platform.HOSTED_ONLY.class)
119119
public static int forPureInstance(ResolvedJavaType type, int size) {
120120
guaranteeEncoding(type, true, size > LAST_SPECIAL_VALUE, "Instance type size must be above special values for encoding: " + size);
121-
int encoding = size;
121+
int encoding = forPureInstance(size);
122122
guaranteeEncoding(type, true, isPureInstance(encoding), "Instance type encoding denotes an instance");
123123
guaranteeEncoding(type, false, isArray(encoding) || isArrayLike(encoding), "Instance type encoding denotes an array-like object");
124124
guaranteeEncoding(type, false, isHybrid(encoding), "Instance type encoding denotes a hybrid");
@@ -128,11 +128,20 @@ public static int forPureInstance(ResolvedJavaType type, int size) {
128128
return encoding;
129129
}
130130

131+
public static int forPureInstance(int size) {
132+
assert size > LAST_SPECIAL_VALUE;
133+
return size;
134+
}
135+
131136
@Platforms(Platform.HOSTED_ONLY.class)
132137
public static int forArray(ResolvedJavaType type, boolean objectElements, int arrayBaseOffset, int arrayIndexShift) {
133138
return forArrayLike(type, false, objectElements, arrayBaseOffset, arrayIndexShift);
134139
}
135140

141+
public static int forArray(boolean objectElements, int arrayBaseOffset, int arrayIndexShift) {
142+
return forArrayLike(false, objectElements, arrayBaseOffset, arrayIndexShift);
143+
}
144+
136145
@Platforms(Platform.HOSTED_ONLY.class)
137146
public static int forHybrid(ResolvedJavaType type, boolean objectElements, int arrayBaseOffset, int arrayIndexShift) {
138147
return forArrayLike(type, true, objectElements, arrayBaseOffset, arrayIndexShift);
@@ -146,9 +155,7 @@ public static int forDynamicHub(ResolvedJavaType type, int vtableOffset, int vta
146155
@Platforms(Platform.HOSTED_ONLY.class)
147156
private static int forArrayLike(ResolvedJavaType type, boolean isHybrid, boolean objectElements, int arrayBaseOffset, int arrayIndexShift) {
148157
assert isHybrid != type.isArray();
149-
int tag = isHybrid ? (objectElements ? ARRAY_TAG_HYBRID_OBJECT_VALUE : ARRAY_TAG_HYBRID_PRIMITIVE_VALUE)
150-
: (objectElements ? ARRAY_TAG_OBJECT_VALUE : ARRAY_TAG_PRIMITIVE_VALUE);
151-
int encoding = (tag << ARRAY_TAG_SHIFT) | (arrayBaseOffset << ARRAY_BASE_SHIFT) | (arrayIndexShift << ARRAY_INDEX_SHIFT_SHIFT);
158+
int encoding = forArrayLike(isHybrid, objectElements, arrayBaseOffset, arrayIndexShift);
152159

153160
guaranteeEncoding(type, true, isArrayLike(encoding), "Array-like object encoding denotes an array-like object");
154161
guaranteeEncoding(type, !isHybrid, isArray(encoding), "Encoding denotes an array");
@@ -165,6 +172,12 @@ private static int forArrayLike(ResolvedJavaType type, boolean isHybrid, boolean
165172
return encoding;
166173
}
167174

175+
private static int forArrayLike(boolean isHybrid, boolean objectElements, int arrayBaseOffset, int arrayIndexShift) {
176+
int tag = isHybrid ? (objectElements ? ARRAY_TAG_HYBRID_OBJECT_VALUE : ARRAY_TAG_HYBRID_PRIMITIVE_VALUE)
177+
: (objectElements ? ARRAY_TAG_OBJECT_VALUE : ARRAY_TAG_PRIMITIVE_VALUE);
178+
return (tag << ARRAY_TAG_SHIFT) | (arrayBaseOffset << ARRAY_BASE_SHIFT) | (arrayIndexShift << ARRAY_INDEX_SHIFT_SHIFT);
179+
}
180+
168181
public static boolean isPrimitive(int encoding) {
169182
return encoding == PRIMITIVE_VALUE;
170183
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/RuntimeClassLoading.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public String toString() {
256256
}
257257

258258
public static ResolvedJavaType createInterpreterType(DynamicHub hub, ResolvedJavaType analysisType) {
259-
return ImageSingletons.lookup(CremaSupport.class).createInterpreterType(hub, analysisType);
259+
return CremaSupport.singleton().createInterpreterType(hub, analysisType);
260260
}
261261

262262
public static void ensureLinked(DynamicHub dynamicHub) {

0 commit comments

Comments
 (0)