Skip to content

Commit

Permalink
Static properties must return their name and if they are final.
Browse files Browse the repository at this point in the history
  • Loading branch information
ansalond committed May 12, 2021
1 parent d030af8 commit e91ca09
Show file tree
Hide file tree
Showing 16 changed files with 132 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,47 +38,48 @@ public class BuilderPropertyTest {
@Test
public void sameBuilderSameProperty() {
StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(StaticPropertyKind.Int);
builder.property(property, "p1", false);
builder.property(property, "p2", false);
StaticProperty property = new DefaultStaticProperty("property", StaticPropertyKind.Int, false);
builder.property(property);
try {
builder.build();
// You cannot add the same property twice
builder.property(property);
Assert.fail();
} catch (RuntimeException e) {
} catch (IllegalArgumentException e) {
// You cannot add the same property twice
Assert.assertEquals("Attempt to reinitialize the offset of a static property. Was it added to more than one builder or multiple times to the same builder?", e.getMessage());
Assert.assertEquals("This builder already contains a property named 'property'", e.getMessage());
}
}

@Test
public void sameBuilderSameName() throws IllegalArgumentException {
StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty p1 = new DefaultStaticProperty(StaticPropertyKind.Int);
StaticProperty p2 = new DefaultStaticProperty(StaticPropertyKind.Int);
builder.property(p1, "p1", false);
StaticProperty p1 = new DefaultStaticProperty("property", StaticPropertyKind.Int, false);
StaticProperty p2 = new DefaultStaticProperty("property", StaticPropertyKind.Int, false);
builder.property(p1);
try {
// You cannot add two properties with the same name
builder.property(p2, "p1", false);
builder.property(p2);
Assert.fail();
} catch (IllegalArgumentException e) {
Assert.assertEquals("This builder already contains a property named 'p1'", e.getMessage());
Assert.assertEquals("This builder already contains a property named 'property'", e.getMessage());
}
}

@Test
public void differentBuildersSameProperty() {
StaticShape.Builder b1 = StaticShape.newBuilder();
StaticShape.Builder b2 = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(StaticPropertyKind.Int);
b1.property(property, "p1", false);
b2.property(property, "p2", false);
StaticProperty property = new DefaultStaticProperty("property", StaticPropertyKind.Int, false);
b1.property(property);
b2.property(property);
b1.build();
try {
// You cannot build shapes that share properties
b2.build();
Assert.fail();
} catch (RuntimeException e) {
Assert.assertEquals("Attempt to reinitialize the offset of a static property. Was it added to more than one builder or multiple times to the same builder?", e.getMessage());
Assert.assertEquals("Attempt to reinitialize the offset of static property 'property' of kind 'Int'.\nWas it added to more than one builder or multiple times to the same builder?",
e.getMessage());
}
}

Expand All @@ -87,9 +88,9 @@ public void propertyName() throws NoSuchFieldException {
Assume.assumeFalse(StorageLayout.ARRAY_BASED);

StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(StaticPropertyKind.Int);
String propertyName = "p1";
builder.property(property, propertyName, false);
String propertyName = "property";
StaticProperty property = new DefaultStaticProperty(propertyName, StaticPropertyKind.Int, false);
builder.property(property);
StaticShape<DefaultStaticObject.Factory> shape = builder.build();
DefaultStaticObject object = shape.getFactory().create();
Field field = object.getClass().getField(propertyName);
Expand All @@ -101,12 +102,12 @@ public void propertyFinal() throws NoSuchFieldException {
Assume.assumeFalse(StorageLayout.ARRAY_BASED);

StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty p1 = new DefaultStaticProperty(StaticPropertyKind.Int);
StaticProperty p2 = new DefaultStaticProperty(StaticPropertyKind.Int);
String p1Name = "p1";
String p2Name = "p2";
builder.property(p1, p1Name, true);
builder.property(p2, p2Name, false);
StaticProperty p1 = new DefaultStaticProperty(p1Name, StaticPropertyKind.Int, true);
StaticProperty p2 = new DefaultStaticProperty(p2Name, StaticPropertyKind.Int, false);
builder.property(p1);
builder.property(p2);
StaticShape<DefaultStaticObject.Factory> shape = builder.build();
DefaultStaticObject object = shape.getFactory().create();
Field f1 = object.getClass().getField(p1Name);
Expand All @@ -121,7 +122,7 @@ public void propertyKind() throws NoSuchFieldException {

StaticShape.Builder builder = StaticShape.newBuilder();
for (StaticPropertyKind kind : StaticPropertyKind.values()) {
builder.property(new DefaultStaticProperty(kind), kind.name(), false);
builder.property(new DefaultStaticProperty(kind.name(), kind, false));
}
StaticShape<DefaultStaticObject.Factory> shape = builder.build();
DefaultStaticObject object = shape.getFactory().create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public interface CustomStaticObjectFactory {
@Test
public void baseClassInheritance() throws NoSuchFieldException {
StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(StaticPropertyKind.Int);
builder.property(property, "field1", false);
StaticProperty property = new DefaultStaticProperty("field1", StaticPropertyKind.Int, false);
builder.property(property);
StaticShape<CustomStaticObjectFactory> shape = builder.build(CustomStaticObject.class, CustomStaticObjectFactory.class);
CustomStaticObject object = shape.getFactory().create();

Expand All @@ -68,16 +68,16 @@ public void baseClassInheritance() throws NoSuchFieldException {
@Test
public void baseShapeInheritance() throws NoSuchFieldException, IllegalAccessException {
StaticShape.Builder b1 = StaticShape.newBuilder();
StaticProperty s1p1 = new DefaultStaticProperty(StaticPropertyKind.Int);
StaticProperty s1p2 = new DefaultStaticProperty(StaticPropertyKind.Int);
b1.property(s1p1, "field1", false);
b1.property(s1p2, "field2", false);
StaticProperty s1p1 = new DefaultStaticProperty("field1", StaticPropertyKind.Int, false);
StaticProperty s1p2 = new DefaultStaticProperty("field2", StaticPropertyKind.Int, false);
b1.property(s1p1);
b1.property(s1p2);
// StaticShape s1 declares 2 properties: s1p1 and s1p2
StaticShape<DefaultStaticObject.Factory> s1 = b1.build();

StaticShape.Builder b2 = StaticShape.newBuilder();
StaticProperty s2p1 = new DefaultStaticProperty(StaticPropertyKind.Int);
b2.property(s2p1, "field1", false);
StaticProperty s2p1 = new DefaultStaticProperty("field1", StaticPropertyKind.Int, false);
b2.property(s2p1);
// StaticShape s2:
// 1. extends s1
// 2. declares one property: s2p1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ public static void init() {
@Theory
public void correctAccessors(TestDescriptor descriptor) {
StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(descriptor.kind);
builder.property(property, "property", false);
StaticProperty property = new DefaultStaticProperty("property", descriptor.kind, false);
builder.property(property);
StaticShape<DefaultStaticObject.Factory> shape = builder.build();
DefaultStaticObject object = shape.getFactory().create();

Expand All @@ -179,13 +179,13 @@ public void wrongAccessors(TestDescriptor expectedDescriptor, TestDescriptor act
Assume.assumeFalse(expectedDescriptor.equals(actualDescriptor));

StaticShape.Builder builder = StaticShape.newBuilder();
StaticProperty property = new DefaultStaticProperty(expectedDescriptor.kind);
builder.property(property, "property", false);
StaticProperty property = new DefaultStaticProperty("property", expectedDescriptor.kind, false);
builder.property(property);
StaticShape<DefaultStaticObject.Factory> shape = builder.build();
DefaultStaticObject object = shape.getFactory().create();

// Check that wrong getters throw exceptions
String expectedExceptionMessage = "Static property of '" + expectedDescriptor.kind.name() + "' kind cannot be accessed as '" + actualDescriptor.kind + "'";
String expectedExceptionMessage = "Static property 'property' of kind '" + expectedDescriptor.kind.name() + "' cannot be accessed as '" + actualDescriptor.kind + "'";
try {
actualDescriptor.getter.get(property, object);
Assert.fail();
Expand All @@ -204,13 +204,13 @@ public void wrongAccessors(TestDescriptor expectedDescriptor, TestDescriptor act
@SuppressWarnings("unused")
public void wrongShape(TestDescriptor descriptor) {
StaticShape.Builder b1 = StaticShape.newBuilder();
StaticProperty p1 = new DefaultStaticProperty(descriptor.kind);
b1.property(p1, "property", false);
StaticProperty p1 = new DefaultStaticProperty("property", descriptor.kind, false);
b1.property(p1);
StaticShape<DefaultStaticObject.Factory> s1 = b1.build();

StaticShape.Builder b2 = StaticShape.newBuilder();
StaticProperty p2 = new DefaultStaticProperty(descriptor.kind);
b2.property(p2, "property", false);
StaticProperty p2 = new DefaultStaticProperty("property", descriptor.kind, false);
b2.property(p2);
StaticShape<DefaultStaticObject.Factory> s2 = b2.build();
DefaultStaticObject o2 = s2.getFactory().create();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import com.oracle.truffle.api.impl.asm.MethodVisitor;
import com.oracle.truffle.api.impl.asm.Opcodes;
import com.oracle.truffle.api.impl.asm.Type;
import com.oracle.truffle.espresso.staticobject.StaticShape.ExtendedProperty;
import org.graalvm.collections.Pair;

import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_FINAL;
Expand Down Expand Up @@ -148,8 +147,8 @@ private static int getObjectFieldOffset(Class<?> c, String fieldName) {
}

@Override
StaticShape<T> generateShape(StaticShape<T> parentShape, Collection<ExtendedProperty> extendedProperties) {
return ArrayBasedStaticShape.create(generatedStorageClass, generatedFactoryClass, (ArrayBasedStaticShape<T>) parentShape, extendedProperties, byteArrayOffset, objectArrayOffset, shapeOffset);
StaticShape<T> generateShape(StaticShape<T> parentShape, Collection<StaticProperty> staticProperties) {
return ArrayBasedStaticShape.create(generatedStorageClass, generatedFactoryClass, (ArrayBasedStaticShape<T>) parentShape, staticProperties, byteArrayOffset, objectArrayOffset, shapeOffset);
}

private static String getStorageConstructorDescriptor(Constructor<?> superConstructor) {
Expand Down Expand Up @@ -229,10 +228,10 @@ private static void addStorageConstructors(ClassVisitor cv, String storageName,
Label lSetPrimitive = new Label();
mv.visitJumpInsn(GOTO, lSetPrimitive);
mv.visitLabel(lNoPrimitives);
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 1, new Object[] {storageName});
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 1, new Object[]{storageName});
mv.visitInsn(ACONST_NULL);
mv.visitLabel(lSetPrimitive);
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 2, new Object[] {storageName, "[B"});
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 2, new Object[]{storageName, "[B"});
mv.visitFieldInsn(PUTFIELD, storageName, "primitive", "[B");

// object = objectArraySize > 0 ? new Object[objectArraySize] : null;
Expand All @@ -245,10 +244,10 @@ private static void addStorageConstructors(ClassVisitor cv, String storageName,
Label lSetObject = new Label();
mv.visitJumpInsn(GOTO, lSetObject);
mv.visitLabel(lNoObjects);
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 1, new Object[] {storageName});
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 1, new Object[]{storageName});
mv.visitInsn(ACONST_NULL);
mv.visitLabel(lSetObject);
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 2, new Object[] {storageName, "[Ljava/lang/Object;"});
mv.visitFrame(F_FULL, frameLocals.length, frameLocals, 2, new Object[]{storageName, "[Ljava/lang/Object;"});
mv.visitFieldInsn(PUTFIELD, storageName, "object", "[Ljava/lang/Object;");

mv.visitInsn(RETURN);
Expand All @@ -275,7 +274,7 @@ private static String[] getCloneMethodExceptions(Method cloneMethod) {

private static void addCloneMethod(Class<?> storageSuperClass, ClassVisitor cv, String className) {
// Prepare array of frame locals for jumps
Object[] frameLocals = new Object[] {className, className};
Object[] frameLocals = new Object[]{className, className};

Method superCloneMethod = getCloneMethod(storageSuperClass);
String superCloneMethodDescriptor = Type.getMethodDescriptor(superCloneMethod);
Expand All @@ -295,14 +294,14 @@ private static void addCloneMethod(Class<?> storageSuperClass, ClassVisitor cv,
Label lSetPrimitive = new Label();
mv.visitJumpInsn(GOTO, lSetPrimitive);
mv.visitLabel(lHasPrimitives);
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 1, new Object[] {className});
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 1, new Object[]{className});
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "primitive", "[B");
mv.visitMethodInsn(INVOKEVIRTUAL, "[B", "clone", "()Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "[B");
mv.visitTypeInsn(CHECKCAST, "[B");
mv.visitLabel(lSetPrimitive);
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 2, new Object[] {className, "[B"});
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 2, new Object[]{className, "[B"});
mv.visitFieldInsn(PUTFIELD, className, "primitive", "[B");

// clone.object = (object == null ? null : (Object[]) object.clone());
Expand All @@ -315,14 +314,14 @@ private static void addCloneMethod(Class<?> storageSuperClass, ClassVisitor cv,
Label lSetObject = new Label();
mv.visitJumpInsn(GOTO, lSetObject);
mv.visitLabel(lHasObjects);
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 1, new Object[] {className});
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 1, new Object[]{className});
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "object", "[Ljava/lang/Object;");
mv.visitMethodInsn(INVOKEVIRTUAL, "[Ljava/lang/Object;", "clone", "()Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
mv.visitLabel(lSetObject);
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 2, new Object[] {className, "[Ljava/lang/Object;"});
mv.visitFrame(Opcodes.F_FULL, 2, frameLocals, 2, new Object[]{className, "[Ljava/lang/Object;"});
mv.visitFieldInsn(PUTFIELD, className, "object", "[Ljava/lang/Object;");

mv.visitVarInsn(ALOAD, 1);
Expand Down Expand Up @@ -394,17 +393,17 @@ private static void addFactoryMethods(ClassVisitor cv, Class<?> storageClass, Cl
}
}

private static Collection<ExtendedProperty> generateStorageProperties() {
private static Collection<StaticProperty> generateStorageProperties() {
return Arrays.asList(
new ExtendedProperty(new DefaultStaticProperty(StaticPropertyKind.BYTE_ARRAY), "primitive", true),
new ExtendedProperty(new DefaultStaticProperty(StaticPropertyKind.OBJECT_ARRAY), "object", true),
new ExtendedProperty(new DefaultStaticProperty(StaticPropertyKind.Object), "shape", true));
new DefaultStaticProperty("primitive", StaticPropertyKind.BYTE_ARRAY, true),
new DefaultStaticProperty("object", StaticPropertyKind.OBJECT_ARRAY, true),
new DefaultStaticProperty("shape", StaticPropertyKind.Object, true));
}

private static Class<?> generateStorage(Class<?> storageSuperClass) {
String storageSuperName = Type.getInternalName(storageSuperClass);
String storageName = generateStorageName();
Collection<ExtendedProperty> arrayProperties = generateStorageProperties();
Collection<StaticProperty> arrayProperties = generateStorageProperties();

ClassWriter storageWriter = new ClassWriter(0);
int storageAccess = ACC_PUBLIC | ACC_SUPER | ACC_SYNTHETIC;
Expand Down
Loading

0 comments on commit e91ca09

Please sign in to comment.