Skip to content
Open
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
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -36,7 +36,6 @@
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.runtime.OptimizedCallTarget;

Expand Down Expand Up @@ -79,7 +78,7 @@ private TestDynamicObject newInstanceWithoutFields() {
@Test
public void testFieldLocation() {
TestDynamicObject obj = newInstanceWithFields();
DynamicObjectLibrary.getUncached().put(obj, "key", 22);
DynamicObject.PutNode.getUncached().put(obj, "key", 22);

Object[] args = {obj, 22};
OptimizedCallTarget callTarget = makeCallTarget(new TestDynamicObjectGetAndPutNode(), "testFieldStoreLoad");
Expand Down Expand Up @@ -107,7 +106,7 @@ public void testFieldLocation() {
@Test
public void testArrayLocation() {
TestDynamicObject obj = newInstanceWithoutFields();
DynamicObjectLibrary.getUncached().put(obj, "key", 22);
DynamicObject.PutNode.getUncached().put(obj, "key", 22);

Object[] args = {obj, 22};
OptimizedCallTarget callTarget = makeCallTarget(new TestDynamicObjectGetAndPutNode(), "testArrayStoreLoad");
Expand Down Expand Up @@ -137,7 +136,8 @@ private static OptimizedCallTarget makeCallTarget(AbstractTestNode testNode, Str
}

static class TestDynamicObjectGetAndPutNode extends AbstractTestNode {
@Child DynamicObjectLibrary dynamicObjectLibrary = DynamicObjectLibrary.getFactory().createDispatched(3);
@Child DynamicObject.GetNode getNode = DynamicObject.GetNode.create();
@Child DynamicObject.PutNode putNode = DynamicObject.PutNode.create();

@Override
public int execute(VirtualFrame frame) {
Expand All @@ -148,22 +148,22 @@ public int execute(VirtualFrame frame) {
DynamicObject obj = (DynamicObject) arg0;
if (frame.getArguments().length > 1) {
Object arg1 = frame.getArguments()[1];
dynamicObjectLibrary.put(obj, "key", (int) arg1);
putNode.put(obj, "key", (int) arg1);
}
int val;
while (true) {
val = getInt(obj, "key");
if (val >= 42) {
break;
}
dynamicObjectLibrary.put(obj, "key", val + 2);
putNode.put(obj, "key", val + 2);
}
return val;
}

private int getInt(DynamicObject obj, Object key) {
try {
return dynamicObjectLibrary.getIntOrDefault(obj, key, null);
return getNode.getIntOrDefault(obj, key, null);
} catch (UnexpectedResultException e) {
throw CompilerDirectives.shouldNotReachHere();
}
Expand Down
22 changes: 22 additions & 0 deletions truffle/benchmarks/interpreter/property_read.sl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
*/

function propRead(obj) {
i = 0;
while(i < 10000000) {
i = i + obj.foo;
}
return i;
}

function run() {
obj = new();
obj.foo = 1;
return propRead(obj);
}

function main() {
return run();
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,62 @@
import org.junit.Test;

import com.oracle.truffle.api.test.AbstractLibraryTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.util.List;

@RunWith(Parameterized.class)
public class CachedFallbackTest extends AbstractLibraryTest {

public enum TestRun {
LIBRARY,
NODES;
}

@Parameter(0) public TestRun run;

@Parameters(name = "{0}")
public static List<TestRun> data() {
return List.of(TestRun.values());
}

record CachedGetNodeWrapper(CachedGetNode node, DynamicObject.GetNode getNode) {
public Object execute(DynamicObject obj, Object key) {
if (node != null) {
return node.execute(obj, key);
} else {
return getNode.getOrDefault(obj, key, null);
}
}
}

record CachedPutNodeWrapper(CachedPutNode node, DynamicObject.PutNode putNode) {
public void execute(DynamicObject obj, Object key, Object value) {
if (node != null) {
node.execute(obj, key, value);
} else {
putNode.put(obj, key, value);
}
}
}

CachedGetNodeWrapper getNode() {
return switch (run) {
case LIBRARY -> new CachedGetNodeWrapper(adopt(CachedGetNodeGen.create()), null);
case NODES -> new CachedGetNodeWrapper(null, DynamicObject.GetNode.create());
};
}

CachedPutNodeWrapper putNode() {
return switch (run) {
case LIBRARY -> new CachedPutNodeWrapper(adopt(CachedPutNodeGen.create()), null);
case NODES -> new CachedPutNodeWrapper(null, DynamicObject.PutNode.create());
};
}

@Test
public void testMixedReceiverTypeSameShape() {
Shape shape = Shape.newBuilder().build();
Expand All @@ -62,13 +115,13 @@ public void testMixedReceiverTypeSameShape() {
String key = "key";
String val = "value";

CachedPutNode writeNode = adopt(CachedPutNodeGen.create());
var writeNode = putNode();
writeNode.execute(o1, key, val);
writeNode.execute(o2, key, val);

assertSame("expected same shape", o1.getShape(), o2.getShape());

CachedGetNode readNode = adopt(CachedGetNodeGen.create());
var readNode = getNode();
assertEquals(val, readNode.execute(o1, key));
assertEquals(val, readNode.execute(o2, key));
}
Expand All @@ -93,7 +146,7 @@ public void testTransition() {

assertSame("expected same shape", o1.getShape(), o2.getShape());

CachedGetNode readNode = adopt(CachedGetNodeGen.create());
var readNode = getNode();
assertEquals(val1, readNode.execute(o1, key1));
assertEquals(val1, readNode.execute(o2, key1));
assertEquals(val2, readNode.execute(o1, key2));
Expand All @@ -120,7 +173,7 @@ public void testMixedReceiverTypeSameShapeWithFallback() {

assertSame("expected same shape", o1.getShape(), o2.getShape());

CachedGetNode readNode = adopt(CachedGetNodeGen.create());
var readNode = getNode();
assertEquals(val1, readNode.execute(o1, key1));
assertEquals(val1, readNode.execute(o2, key1));
assertEquals(val2, readNode.execute(o1, key2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@
import java.util.Arrays;
import java.util.List;

import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.Assert;
Expand All @@ -55,11 +51,13 @@
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.oracle.truffle.api.test.AbstractParametrizedLibraryTest;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;

@SuppressWarnings("deprecation")
@RunWith(Parameterized.class)
public class ConstantLocationTest extends AbstractParametrizedLibraryTest {
public class ConstantLocationTest extends ParametrizedDynamicObjectTest {

@Parameters(name = "{0}")
public static List<TestRun> data() {
Expand All @@ -82,7 +80,7 @@ private DynamicObject newInstanceWithConstant() {
public void testConstantLocation() {
DynamicObject object = newInstanceWithConstant();

DynamicObjectLibrary library = createLibrary(DynamicObjectLibrary.class, object);
var library = createLibrary(object);

Assert.assertSame(value, library.getOrDefault(object, "constant", null));

Expand Down Expand Up @@ -113,7 +111,7 @@ public void testConstantLocation() {
public void testMigrateConstantLocation() {
DynamicObject object = newInstanceWithConstant();

DynamicObjectLibrary library = createLibrary(DynamicObjectLibrary.class, object);
var library = createLibrary(object);

Assert.assertSame(shapeWithConstant, object.getShape());
Assert.assertSame(value, library.getOrDefault(object, "constant", null));
Expand All @@ -131,7 +129,7 @@ public void testAddConstantLocation() throws com.oracle.truffle.api.object.Incom

DynamicObject object = newInstance();

DynamicObjectLibrary library = createLibrary(DynamicObjectLibrary.class, object);
var library = createLibrary(object);

property.getLocation().set(object, value, rootShape, shapeWithConstant);
Assert.assertSame(shapeWithConstant, object.getShape());
Expand All @@ -158,7 +156,7 @@ public void testGetConstantValue() {

DynamicObject object = newInstance();

DynamicObjectLibrary library = createLibrary(DynamicObjectLibrary.class, object);
var library = createLibrary(object);
library.put(object, "other", "otherValue");

Property otherProperty = object.getShape().getProperty("other");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
import java.util.stream.Stream;

import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Location;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;
Expand Down Expand Up @@ -159,21 +158,21 @@ private static String shapeLocationsToString(Shape shape) {
return sb.toString();
}

@SuppressWarnings("deprecation")
public static Map<Object, Object> archive(DynamicObject object) {
DynamicObjectLibrary lib = DynamicObjectLibrary.getFactory().getUncached(object);
Map<Object, Object> archive = new HashMap<>();
for (Property property : lib.getPropertyArray(object)) {
archive.put(property.getKey(), lib.getOrDefault(object, property.getKey(), null));
for (Property property : object.getShape().getPropertyList()) {
archive.put(property.getKey(), property.get(object, false));
}
return archive;
}

@SuppressWarnings("deprecation")
public static boolean verifyValues(DynamicObject object, Map<Object, Object> archive) {
DynamicObjectLibrary lib = DynamicObjectLibrary.getFactory().getUncached(object);
for (Property property : lib.getPropertyArray(object)) {
for (Property property : object.getShape().getPropertyList()) {
Object key = property.getKey();
Object before = archive.get(key);
Object after = lib.getOrDefault(object, key, null);
Object after = property.get(object, false);
assertEquals("before != after for key: " + key, after, before);
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,21 @@
import static org.hamcrest.MatcherAssert.assertThat;

import java.lang.invoke.MethodHandles;
import java.util.List;

import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;
import org.junit.Test;
import com.oracle.truffle.api.object.Shape;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.oracle.truffle.api.test.AbstractLibraryTest;
@RunWith(Parameterized.class)
public class DynamicObjectConstructorTest extends ParametrizedDynamicObjectTest {

public class DynamicObjectConstructorTest extends AbstractLibraryTest {
@Parameters(name = "{0}")
public static List<TestRun> data() {
return List.of(TestRun.UNCACHED_ONLY);
}

@Test
public void testIncompatibleShape() {
Expand All @@ -65,7 +72,7 @@ public void testIncompatibleShape() {
public void testNonEmptyShape() {
Shape emptyShape = Shape.newBuilder().layout(TestDynamicObjectDefault.class, MethodHandles.lookup()).build();
TestDynamicObjectDefault obj = new TestDynamicObjectDefault(emptyShape);
DynamicObjectLibrary.getUncached().put(obj, "key", "value");
uncachedLibrary().put(obj, "key", "value");
Shape nonEmptyShape = obj.getShape();

assertFails(() -> new TestDynamicObjectDefault(nonEmptyShape), IllegalArgumentException.class,
Expand Down
Loading
Loading