Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import static com.oracle.truffle.espresso.classfile.Constants.ACC_SUPER;
import static com.oracle.truffle.espresso.classfile.Constants.ACC_SYNCHRONIZED;
import static com.oracle.truffle.espresso.classfile.Constants.ACC_SYNTHETIC;
import static com.oracle.truffle.espresso.classfile.Constants.ACC_VALUE_BASED;
import static com.oracle.truffle.espresso.classfile.Constants.ACC_VARARGS;
import static com.oracle.truffle.espresso.classfile.Constants.ACC_VOLATILE;
import static com.oracle.truffle.espresso.classfile.Constants.JVM_RECOGNIZED_CLASS_MODIFIERS;
Expand Down Expand Up @@ -893,7 +894,7 @@ RuntimeVisibleAnnotationsAttribute parseRuntimeVisibleAnnotations(int attributeS
flags = switch (location) {
case Method -> parseMethodVMAnnotations(subStream);
case Field -> parseFieldVMAnnotations(subStream);
case Class -> 0;
case Class -> parseClassVMAnnotations(subStream);
};
}

Expand Down Expand Up @@ -943,6 +944,20 @@ private int parseFieldVMAnnotations(ClassfileStream subStream) {
}
return flags;
}

private int parseClassVMAnnotations(ClassfileStream subStream) {
int flags = 0;
int count = subStream.readU2();
for (int j = 0; j < count; j++) {
int typeIndex = parseAnnotation(subStream);
// Validation of the type is done at runtime by guest java code.
Symbol<?> annotType = pool.utf8At(typeIndex, "annotation type");
if (ParserTypes.jdk_internal_ValueBased.equals(annotType)) {
flags |= ACC_VALUE_BASED;
}
}
return flags;
}
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -1111,7 +1126,10 @@ private static Attribute[] spawnAttributesArray(int attributeCount) {
return attributeCount == 0 ? Attribute.EMPTY_ARRAY : new Attribute[attributeCount];
}

private static int parseAnnotation(ClassfileStream subStream) {
/**
* Parse one annotation in an annotation attribute and return the annotation type index.
*/
public static int parseAnnotation(ClassfileStream subStream) {
int typeIndex = subStream.readU2();
int numElementValuePairs = subStream.readU2();
for (int k = 0; k < numElementValuePairs; k++) {
Expand Down Expand Up @@ -1248,6 +1266,10 @@ private Attribute[] parseClassAttributes() throws ValidationException {
throw classFormatError("Duplicate PermittedSubclasses attribute");
}
classAttributes[i] = permittedSubclasses = parsePermittedSubclasses(attributeName);
} else if (attributeName.equals(ParserNames.RuntimeVisibleAnnotations)) {
RuntimeVisibleAnnotationsAttribute annotations = commonAttributeParser.parseRuntimeVisibleAnnotations(attributeSize, AnnotationLocation.Class);
classFlags |= annotations.flags;
classAttributes[i] = annotations.attribute;
} else {
Attribute attr = commonAttributeParser.parseCommonAttribute(attributeName, attributeSize);
// stream.skip(attributeSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ public final class Constants {

// Not part of the spec, used internally by the VM.
// Methods
public static final int ACC_FINALIZER = 0x00010000;
public static final int ACC_FORCE_INLINE = 0x00020000;
public static final int ACC_LAMBDA_FORM_COMPILED = 0x00040000;
public static final int ACC_CALLER_SENSITIVE = 0x00080000;
public static final int ACC_HIDDEN = 0x00100000; // also for fields
public static final int ACC_SCOPED = 0x00200000;
public static final int ACC_DONT_INLINE = 0x00400000;
// Classes
public static final int ACC_FINALIZER = 0x00010000;
public static final int ACC_IS_HIDDEN_CLASS = 0x04000000; // synchronized with JVM_ACC_IS_HIDDEN_CLASS
public static final int ACC_VALUE_BASED = 0x00020000;
// Fields
public static final int ACC_STABLE = 0x00010000;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public static final class ParserTypes {
public static final Symbol<Type> jdk_internal_vm_annotation_ForceInline = SYMBOLS.putType("Ljdk/internal/vm/annotation/ForceInline;");
public static final Symbol<Type> java_lang_invoke_DontInline = SYMBOLS.putType("Ljava/lang/invoke/DontInline;");
public static final Symbol<Type> jdk_internal_vm_annotation_DontInline = SYMBOLS.putType("Ljdk/internal/vm/annotation/DontInline;");
public static final Symbol<Type> jdk_internal_ValueBased = SYMBOLS.putType("Ljdk/internal/ValueBased;");

// ScopedMemoryAccess
public static final Symbol<Type> jdk_internal_misc_ScopedMemoryAccess$Scoped = SYMBOLS.putType("Ljdk/internal/misc/ScopedMemoryAccess$Scoped;");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public TypeSymbols getTypes() {
* @return Array of Type symbols representing parameter types followed by return type
*/
public Symbol<Type>[] parsed(Symbol<Signature> signature) {
return parse(SignatureSymbols.this.getTypes(), signature, 0);
return parse(SignatureSymbols.this.getTypes(), signature);
}

/**
Expand Down Expand Up @@ -186,12 +186,12 @@ private static Symbol<Type> toBasic(Symbol<Type> type) {
* @throws ParserException.ClassFormatError if {the signature is not well-formed
*/
@SuppressWarnings({"rawtypes", "unchecked"})
static Symbol<Type>[] parse(TypeSymbols typeSymbols, Symbol<Signature> signature, int startIndex) throws ParserException.ClassFormatError {
if ((startIndex > signature.length() - 3) || signature.byteAt(startIndex) != '(') {
public static Symbol<Type>[] parse(TypeSymbols typeSymbols, Symbol<Signature> signature) throws ParserException.ClassFormatError {
if ((signature.length() < 3) || signature.byteAt(0) != '(') {
throw new ParserException.ClassFormatError("Invalid method signature: " + signature);
}
final List<Symbol<Type>> buf = new ArrayList<>();
int i = startIndex + 1;
int i = 1;
while (signature.byteAt(i) != ')') {
final Symbol<Type> descriptor = typeSymbols.parse(signature, i, true);
buf.add(descriptor);
Expand Down
2 changes: 1 addition & 1 deletion substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ def prevent_build_path_in_libgraal():
use_modules='image',
jar_distributions=['substratevm:SVM_JDWP_SERVER'],
build_args=libsvmjdwp_build_args + [
'--features=com.oracle.svm.jdwp.server.ServerJDWPFeature',
'--features=com.oracle.svm.jdwp.server.ServerJDWPFeature,com.oracle.svm.hosted.SymbolsFeature',
],
headers=False,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,33 @@
*/
package com.oracle.svm.core.hub;

import java.util.List;

import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.svm.espresso.classfile.ParserKlass;

import jdk.vm.ci.meta.ResolvedJavaType;

public interface CremaSupport {
@Platforms(Platform.HOSTED_ONLY.class)
ResolvedJavaType createInterpreterType(DynamicHub hub, ResolvedJavaType analysisType);

int getAfterFieldsOffset(DynamicHub hub);

interface CremaDispatchTable {
int vtableLength();

int itableLength(Class<?> iface);
}

CremaDispatchTable getDispatchTable(ParserKlass parsed, Class<?> superClass, List<Class<?>> superInterfaces);

void fillDynamicHubInfo(DynamicHub hub, CremaDispatchTable table, List<Class<?>> transitiveSuperInterfaces, int[] interfaceIndices);

static CremaSupport singleton() {
return ImageSingletons.lookup(CremaSupport.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
import jdk.internal.reflect.FieldAccessor;
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaType;
import sun.reflect.annotation.AnnotationType;
import sun.reflect.generics.factory.GenericsFactory;
Expand Down Expand Up @@ -432,47 +433,95 @@ public DynamicHub(Class<?> hostedJavaClass, String name, byte hubType, Reference
*/
@NeverInline("Fields of DynamicHub are immutable. Immutable reads could float above ANY_LOCATION writes.")
public static DynamicHub allocate(String name, DynamicHub superHub, Object interfacesEncoding, DynamicHub componentHub, String sourceFileName,
int modifiers, short flags, ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName,
Object declaringClass, String signature) {
int modifiers, short flags, ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Module module,
Object declaringClass, String signature, int typeID,
short numClassTypes,
short typeIDDepth,
short numInterfacesTypes,
int[] openTypeWorldTypeCheckSlots, int vTableEntries,
int afterFieldsOffset, boolean valueBased) {
VMError.guarantee(RuntimeClassLoading.isSupported());

ReferenceType referenceType = ReferenceType.computeReferenceType(DynamicHub.toClass(superHub));
// GR-59683: HubType.OBJECT_ARRAY?
byte hubType = HubType.INSTANCE;
if (referenceType != ReferenceType.None) {
hubType = HubType.REFERENCE_INSTANCE;
byte hubType;
if (componentHub != null) {
if (componentHub.isPrimitive()) {
hubType = HubType.PRIMITIVE_ARRAY;
} else {
hubType = HubType.OBJECT_ARRAY;
}
} else {
if (referenceType == ReferenceType.None) {
hubType = HubType.INSTANCE;
} else {
hubType = HubType.REFERENCE_INSTANCE;
}
}

// GR-62339
Module module = null;

// GR-59683: Setup interpreter metadata at run-time.
ResolvedJavaType interpreterType = null;

DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature,
interpreterType);
DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);

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

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

// GR-60069: Determine size for instance and offsets for monitor and identityHashCode
int layoutEncoding = 0x40;
char monitorOffset = 0;
char identityHashOffset = 0;
assert !isFlagSet(flags, IS_PRIMITIVE_FLAG_BIT);
boolean isInterface = isFlagSet(flags, IS_INTERFACE_FLAG_BIT);
int layoutEncoding;
int monitorOffset = 0;
int identityHashOffset = 0;

// See also similar logic in UniverseBuilder.buildHubs
ObjectLayout ol = ConfigurationValues.getObjectLayout();
if (componentHub != null) {
// array
JavaKind componentKind = JavaKind.fromJavaClass(DynamicHub.toClass(componentHub));
boolean isObject = (componentKind == JavaKind.Object);
layoutEncoding = LayoutEncoding.forArray(isObject, ol.getArrayBaseOffset(componentKind), ol.getArrayIndexShift(componentKind));
if (ol.isIdentityHashFieldInObjectHeader() || ol.isIdentityHashFieldAtTypeSpecificOffset()) {
identityHashOffset = NumUtil.safeToInt(ol.getObjectHeaderIdentityHashOffset());
}
} else if (isInterface) {
layoutEncoding = LayoutEncoding.forInterface();
} else {
// instance class
assert !"java.lang.Class".equals(name);
/*
* @Hybrid types are not supported. The absence of the annotation is assumed to be
* checked by callers. See AbstractRuntimeClassRegistry.checkNotHybrid.
*/
if (Modifier.isAbstract(modifiers)) {
layoutEncoding = LayoutEncoding.forAbstract();
} else {
int instanceSize = afterFieldsOffset;

boolean needsMonitorOffset = !valueBased;
if (needsMonitorOffset) {
// GR-60069 could look for gaps
int size = ol.getReferenceSize();
int bits = size - 1;
int alignmentAdjust = ((instanceSize + bits) & ~bits) - instanceSize;
monitorOffset = instanceSize + alignmentAdjust;
instanceSize = monitorOffset + size;
}

// GR-59687: Determine typecheck related infos
int typeID = 0;
short typeIDDepth = 0;
short numClassTypes = 2;
short numInterfacesTypes = 0;
int[] openTypeWorldTypeCheckSlots = new int[numClassTypes + (numInterfacesTypes * 2)];
if (ol.isIdentityHashFieldInObjectHeader()) {
identityHashOffset = ol.getObjectHeaderIdentityHashOffset();
} else if (ol.isIdentityHashFieldAtTypeSpecificOffset() || ol.isIdentityHashFieldOptional()) {
// GR-60069 could look for gaps
int bits = Integer.BYTES - 1;
int alignmentAdjust = ((instanceSize + bits) & ~bits) - instanceSize;
identityHashOffset = instanceSize + alignmentAdjust;
instanceSize = identityHashOffset + Integer.BYTES;
} else {
throw VMError.shouldNotReachHere("Unexpected identity hash mode");
}
layoutEncoding = LayoutEncoding.forPureInstance(ol.alignUp(instanceSize));
}
}

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

/*
Expand Down Expand Up @@ -519,8 +568,10 @@ public static DynamicHub allocate(String name, DynamicHub superHub, Object inter
writeShort(hub, dynamicHubOffsets.getNumInterfaceTypesOffset(), numInterfacesTypes);
writeObject(hub, dynamicHubOffsets.getOpenTypeWorldTypeCheckSlotsOffset(), openTypeWorldTypeCheckSlots);

writeChar(hub, dynamicHubOffsets.getMonitorOffsetOffset(), monitorOffset);
writeChar(hub, dynamicHubOffsets.getIdentityHashOffsetOffset(), identityHashOffset);
VMError.guarantee(monitorOffset == (char) monitorOffset);
VMError.guarantee(identityHashOffset == (char) identityHashOffset);
writeChar(hub, dynamicHubOffsets.getMonitorOffsetOffset(), (char) monitorOffset);
writeChar(hub, dynamicHubOffsets.getIdentityHashOffsetOffset(), (char) identityHashOffset);

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,17 @@ public final class DynamicHubCompanion {
static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {

return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature, null);
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
}

static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature,
ResolvedJavaType interpreterType) {
ClassLoader classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
assert RuntimeClassLoading.isSupported();
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature, interpreterType);
return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature);
}

private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers,
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature, ResolvedJavaType interpreterType) {
Object classLoader, Class<?> nestHost, String simpleBinaryName, Object declaringClass, String signature) {
this.module = module;
this.superHub = superHub;
this.sourceFileName = sourceFileName;
Expand All @@ -171,6 +170,5 @@ private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFil
this.signature = signature;

this.classLoader = classLoader;
this.interpreterType = interpreterType;
}
}
Loading
Loading