Skip to content

Commit

Permalink
Implement records
Browse files Browse the repository at this point in the history
  • Loading branch information
rakachan committed Jul 19, 2021
1 parent 459dc52 commit aca4842
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,17 @@
package com.oracle.truffle.espresso.classfile.attributes;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.espresso.classfile.RuntimeConstantPool;
import com.oracle.truffle.espresso.descriptors.Symbol;
import com.oracle.truffle.espresso.descriptors.Symbol.Name;
import com.oracle.truffle.espresso.descriptors.Symbol.Signature;
import com.oracle.truffle.espresso.descriptors.Symbol.Type;
import com.oracle.truffle.espresso.impl.Field;
import com.oracle.truffle.espresso.impl.Method;
import com.oracle.truffle.espresso.impl.ObjectKlass;
import com.oracle.truffle.espresso.meta.Meta;
import com.oracle.truffle.espresso.runtime.Attribute;
import com.oracle.truffle.espresso.runtime.StaticObject;

public class RecordAttribute extends Attribute {
public static final Symbol<Name> NAME = Name.Record;
Expand All @@ -50,5 +58,51 @@ public RecordComponentInfo(int name, int descriptor, Attribute[] attributes) {
this.descriptor = (char) descriptor;
this.attributes = attributes;
}

public StaticObject toGuestComponent(Meta meta, ObjectKlass klass) {
assert meta.getJavaVersion().java16OrLater();
RuntimeConstantPool pool = klass.getConstantPool();
StaticObject component = meta.java_lang_reflect_RecordComponent.allocateInstance();
Symbol<Name> nameSymbol = pool.symbolAt(name);
Symbol<Type> typeSymbol = pool.symbolAt(descriptor);
Symbol<Signature> signature = meta.getSignatures().makeRaw(Type._void, typeSymbol);
meta.java_lang_reflect_RecordComponent_clazz.setObject(component, klass.mirror());
meta.java_lang_reflect_RecordComponent_name.setObject(component, meta.toGuestString(nameSymbol));
meta.java_lang_reflect_RecordComponent_type.setObject(component, meta.resolveSymbolAndAccessCheck(typeSymbol, klass).mirror());

// Find and set accessor
Method m = klass.lookupMethod(nameSymbol, signature);
boolean validMethod = m != null && !m.isStatic() && !m.isConstructor();
meta.java_lang_reflect_RecordComponent_accessor.setObject(component, validMethod ? m.makeMirror() : StaticObject.NULL);

// Find and set generic signature
SignatureAttribute genericSignatureAttribute = (SignatureAttribute) getAttribute(SignatureAttribute.NAME);
meta.java_lang_reflect_RecordComponent_signature.setObject(component,
genericSignatureAttribute != null ? meta.toGuestString(pool.symbolAt(genericSignatureAttribute.getSignatureIndex())) : StaticObject.NULL);

// Find and set annotations
doAnnotation(component, Name.RuntimeVisibleAnnotations, meta.java_lang_reflect_RecordComponent_annotations, meta);
doAnnotation(component, Name.RuntimeVisibleAnnotations, meta.java_lang_reflect_RecordComponent_typeAnnotations, meta);

return component;
}

private void doAnnotation(StaticObject component, Symbol<Name> attrName, Field f, Meta meta) {
Attribute attr = getAttribute(attrName);
f.setObject(component, attr == null ? StaticObject.NULL : StaticObject.wrap(attr.getData(), meta));
}

public Attribute getAttribute(Symbol<Name> attributeName) {
for (Attribute attr : attributes) {
if (attr.getName().equals(attributeName)) {
return attr;
}
}
return null;
}
}

public RecordComponentInfo[] getComponents() {
return components;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ public static void ensureInitialized() {
// j.l.Module
public static final Symbol<Name> loader = StaticSymbols.putName("loader");

// j.l.RecordComponent
public static final Symbol<Name> accessor = StaticSymbols.putName("accessor");
public static final Symbol<Name> annotations = StaticSymbols.putName("annotations");
public static final Symbol<Name> typeAnnotations = StaticSymbols.putName("typeAnnotations");

// j.l.String
public static final Symbol<Name> hash = StaticSymbols.putName("hash");
public static final Symbol<Name> hashCode = StaticSymbols.putName("hashCode");
Expand Down Expand Up @@ -764,6 +769,10 @@ public static void ensureInitialized() {
// Modules
public static final Symbol<Type> java_lang_Module = StaticSymbols.putType("Ljava/lang/Module;");

// Record
public static final Symbol<Type> java_lang_Record = StaticSymbols.putType("Ljava/lang/Record;");
public static final Symbol<Type> java_lang_reflect_RecordComponent = StaticSymbols.putType("Ljava/lang/reflect/RecordComponent;");

// Unsafe Constants (required for 13+)
public static final Symbol<Type> jdk_internal_misc_UnsafeConstants = StaticSymbols.putType("Ljdk/internal/misc/UnsafeConstants;");

Expand Down Expand Up @@ -912,6 +921,19 @@ public static void ensureInitialized() {
public static final Symbol<Signature> java_util_Iterator = StaticSymbols.putSignature(Type.java_util_Iterator);
public static final Symbol<Signature> java_util_Set = StaticSymbols.putSignature(Type.java_util_Set);

public static final Symbol<Signature> java_lang_reflect_Method_init_signature = StaticSymbols.putSignature(Type._void,
/* declaringClass */ Type.java_lang_Class,
/* name */ Type.java_lang_String,
/* parameterTypes */ Type.java_lang_Class_array,
/* returnType */ Type.java_lang_Class,
/* checkedExceptions */ Type.java_lang_Class_array,
/* modifiers */ Type._int,
/* slot */ Type._int,
/* signature */ Type.java_lang_String,
/* annotations */ Type._byte_array,
/* parameterAnnotations */ Type._byte_array,
/* annotationDefault */ Type._byte_array);

public static final Symbol<Signature> MethodType_Class_Class = StaticSymbols.putSignature(Type.java_lang_invoke_MethodType, Type.java_lang_Class, Type.java_lang_Class_array);
public static final Symbol<Signature> MethodType_String_ClassLoader = StaticSymbols.putSignature(Type.java_lang_invoke_MethodType, Type.java_lang_String, Type.java_lang_ClassLoader);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.IntFunction;
import java.util.logging.Level;

import com.oracle.truffle.api.Assumption;
Expand Down Expand Up @@ -1176,6 +1177,73 @@ public boolean isRemovedByRedefition() {
return !removedByRedefinition.isValid();
}

public StaticObject makeMirror() {
Meta meta = getMeta();
Attribute rawRuntimeVisibleAnnotations = getAttribute(Name.RuntimeVisibleAnnotations);
StaticObject runtimeVisibleAnnotations = rawRuntimeVisibleAnnotations != null
? StaticObject.wrap(rawRuntimeVisibleAnnotations.getData(), meta)
: StaticObject.NULL;

Attribute rawRuntimeVisibleParameterAnnotations = getAttribute(Name.RuntimeVisibleParameterAnnotations);
StaticObject runtimeVisibleParameterAnnotations = rawRuntimeVisibleParameterAnnotations != null
? StaticObject.wrap(rawRuntimeVisibleParameterAnnotations.getData(), meta)
: StaticObject.NULL;

Attribute rawRuntimeVisibleTypeAnnotations = getAttribute(Name.RuntimeVisibleTypeAnnotations);
StaticObject runtimeVisibleTypeAnnotations = rawRuntimeVisibleTypeAnnotations != null
? StaticObject.wrap(rawRuntimeVisibleTypeAnnotations.getData(), meta)
: StaticObject.NULL;

Attribute rawAnnotationDefault = getAttribute(Name.AnnotationDefault);
StaticObject annotationDefault = rawAnnotationDefault != null
? StaticObject.wrap(rawAnnotationDefault.getData(), meta)
: StaticObject.NULL;
final Klass[] rawParameterKlasses = resolveParameterKlasses();
StaticObject parameterTypes = meta.java_lang_Class.allocateReferenceArray(
getParameterCount(),
new IntFunction<StaticObject>() {
@Override
public StaticObject apply(int j) {
return rawParameterKlasses[j].mirror();
}
});

final Klass[] rawCheckedExceptions = getCheckedExceptions();
StaticObject guestCheckedExceptions = meta.java_lang_Class.allocateReferenceArray(rawCheckedExceptions.length, new IntFunction<StaticObject>() {
@Override
public StaticObject apply(int j) {
return rawCheckedExceptions[j].mirror();
}
});

SignatureAttribute signatureAttribute = (SignatureAttribute) getAttribute(Name.Signature);
StaticObject guestGenericSignature = StaticObject.NULL;
if (signatureAttribute != null) {
String sig = getConstantPool().symbolAt(signatureAttribute.getSignatureIndex(), "signature").toString();
guestGenericSignature = meta.toGuestString(sig);
}

StaticObject instance = meta.java_lang_reflect_Method.allocateInstance();

meta.java_lang_reflect_Method_init.invokeDirect(
/* this */ instance,
/* declaringClass */ getDeclaringKlass().mirror(),
/* name */ getContext().getStrings().intern(getName()),
/* parameterTypes */ parameterTypes,
/* returnType */ resolveReturnKlass().mirror(),
/* checkedExceptions */ guestCheckedExceptions,
/* modifiers */ getMethodModifiers(),
/* slot */ getVTableIndex(),
/* signature */ guestGenericSignature,

/* annotations */ runtimeVisibleAnnotations,
/* parameterAnnotations */ runtimeVisibleParameterAnnotations,
/* annotationDefault */ annotationDefault);
meta.HIDDEN_METHOD_KEY.setHiddenObject(instance, this);
meta.HIDDEN_METHOD_RUNTIME_VISIBLE_TYPE_ANNOTATIONS.setHiddenObject(instance, runtimeVisibleTypeAnnotations);
return instance;
}

public final class MethodVersion implements MethodRef {
private final Assumption assumption;
private final RuntimeConstantPool pool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.oracle.truffle.espresso.classfile.attributes.NestHostAttribute;
import com.oracle.truffle.espresso.classfile.attributes.NestMembersAttribute;
import com.oracle.truffle.espresso.classfile.attributes.PermittedSubclassesAttribute;
import com.oracle.truffle.espresso.classfile.attributes.RecordAttribute;
import com.oracle.truffle.espresso.classfile.attributes.SignatureAttribute;
import com.oracle.truffle.espresso.classfile.attributes.SourceDebugExtensionAttribute;
import com.oracle.truffle.espresso.descriptors.Names;
Expand Down Expand Up @@ -1103,10 +1104,8 @@ public void initSelfReferenceInPool() {
getConstantPool().setKlassAt(getLinkedKlass().getParserKlass().getThisKlassIndex(), this);
}

@SuppressWarnings("static-method")
public boolean isRecord() {
// TODO:
return false;
return isFinalFlagSet() && getSuperKlass() == getMeta().java_lang_Record && getAttribute(RecordAttribute.NAME) != null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class DiffVersionLoadHelper {
static final VersionRange VERSION_9_OR_HIGHER = VersionRange.higher(9);
static final VersionRange VERSION_11_OR_HIGHER = VersionRange.higher(11);
static final VersionRange VERSION_11_TO_17 = new VersionRange(11, 17);
static final VersionRange VERSION_16_OR_HIGHER = VersionRange.higher(16);
static final VersionRange VERSION_17_OR_HIGHER = VersionRange.higher(17);
static final VersionRange ALL = new VersionRange(0, JavaVersion.LATEST_SUPPORTED);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
package com.oracle.truffle.espresso.meta;

import static com.oracle.truffle.espresso.EspressoOptions.SpecCompliancyMode.HOTSPOT;
import static com.oracle.truffle.espresso.meta.DiffVersionLoadHelper.ALL;
import static com.oracle.truffle.espresso.meta.DiffVersionLoadHelper.VERSION_16_OR_HIGHER;
import static com.oracle.truffle.espresso.meta.DiffVersionLoadHelper.VERSION_8_OR_LOWER;
import static com.oracle.truffle.espresso.meta.DiffVersionLoadHelper.VERSION_9_OR_HIGHER;
import static com.oracle.truffle.espresso.meta.DiffVersionLoadHelper.VersionRange.higher;
Expand Down Expand Up @@ -311,6 +313,7 @@ public Meta(EspressoContext context) {
java_lang_reflect_Constructor_signature = java_lang_reflect_Constructor.requireDeclaredField(Name.signature, Type.java_lang_String);

java_lang_reflect_Method = knownKlass(Type.java_lang_reflect_Method);
java_lang_reflect_Method_init = java_lang_reflect_Method.lookupDeclaredMethod(Name._init_, Signature.java_lang_reflect_Method_init_signature);
HIDDEN_METHOD_KEY = java_lang_reflect_Method.requireHiddenField(Name.HIDDEN_METHOD_KEY);
HIDDEN_METHOD_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = java_lang_reflect_Method.requireHiddenField(Name.HIDDEN_METHOD_RUNTIME_VISIBLE_TYPE_ANNOTATIONS);
java_lang_reflect_Method_root = java_lang_reflect_Method.requireDeclaredField(Name.root, Type.java_lang_reflect_Method);
Expand Down Expand Up @@ -548,6 +551,34 @@ public Meta(EspressoContext context) {
java_lang_Class_module = null;
}

java_lang_Record = diff() //
.klass(VERSION_16_OR_HIGHER, Type.java_lang_Record) //
.notRequiredKlass();
java_lang_reflect_RecordComponent = diff() //
.klass(VERSION_16_OR_HIGHER, Type.java_lang_reflect_RecordComponent) //
.notRequiredKlass();
java_lang_reflect_RecordComponent_clazz = diff() //
.field(ALL, Name.clazz, Type.java_lang_Class) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_name = diff() //
.field(ALL, Name.name, Type.java_lang_String) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_type = diff() //
.field(ALL, Name.type, Type.java_lang_Class) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_accessor = diff() //
.field(ALL, Name.accessor, Type.java_lang_reflect_Method) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_signature = diff() //
.field(ALL, Name.signature, Type.java_lang_String) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_annotations = diff() //
.field(ALL, Name.annotations, Type._byte_array) //
.notRequiredField(java_lang_reflect_RecordComponent);
java_lang_reflect_RecordComponent_typeAnnotations = diff() //
.field(ALL, Name.typeAnnotations, Type._byte_array) //
.notRequiredField(java_lang_reflect_RecordComponent);

sun_reflect_MagicAccessorImpl = diff() //
.klass(VERSION_8_OR_LOWER, Type.sun_reflect_MagicAccessorImpl) //
.klass(VERSION_9_OR_HIGHER, Type.jdk_internal_reflect_MagicAccessorImpl) //
Expand Down Expand Up @@ -947,6 +978,16 @@ private DiffVersionLoadHelper diff() {
public final Field java_lang_Module_loader;
public final Field HIDDEN_MODULE_ENTRY;

public final ObjectKlass java_lang_Record;
public final ObjectKlass java_lang_reflect_RecordComponent;
public final Field java_lang_reflect_RecordComponent_clazz;
public final Field java_lang_reflect_RecordComponent_name;
public final Field java_lang_reflect_RecordComponent_type;
public final Field java_lang_reflect_RecordComponent_accessor;
public final Field java_lang_reflect_RecordComponent_signature;
public final Field java_lang_reflect_RecordComponent_annotations;
public final Field java_lang_reflect_RecordComponent_typeAnnotations;

public final ObjectKlass java_lang_AssertionStatusDirectives;
public final Field java_lang_AssertionStatusDirectives_classes;
public final Field java_lang_AssertionStatusDirectives_classEnabled;
Expand All @@ -968,6 +1009,7 @@ private DiffVersionLoadHelper diff() {
public final ObjectKlass sun_reflect_DelegatingClassLoader;

public final ObjectKlass java_lang_reflect_Method;
public final Method java_lang_reflect_Method_init;
public final Field HIDDEN_METHOD_RUNTIME_VISIBLE_TYPE_ANNOTATIONS;
public final Field HIDDEN_METHOD_KEY;
public final Field java_lang_reflect_Method_root;
Expand Down
Loading

0 comments on commit aca4842

Please sign in to comment.