Skip to content

[GR-65415] Fixes for the extended dynamic object layout. #11439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 19, 2025
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
4 changes: 3 additions & 1 deletion truffle/mx.truffle/mx_truffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,9 @@ def _truffle_gate_runner(args, tasks):
with Task('Truffle Signature Tests', tasks, tags=TruffleGateTags.sigtest) as t:
if t: sigtest(['--check', 'binary'])
with Task('Truffle UnitTests', tasks, tags=TruffleGateTags.truffle_test) as t:
if t: unittest(list(['--suite', 'truffle', '--enable-timing', '--verbose', '--max-class-failures=25']))
if t:
unittest(['--suite', 'truffle', '--enable-timing', '--verbose', '--max-class-failures=25'])
unittest(['--suite', 'truffle', '--enable-timing', '-Dtruffle.object.LayoutFactory=com.oracle.truffle.api.object.CoreLayoutFactory', 'com.oracle.truffle.object'])
if jdk.javaCompliance >= '22':
with Task('Truffle NFI tests with Panama Backend', tasks, tags=TruffleGateTags.panama_test) as t:
if t:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
*/
package com.oracle.truffle.object.basic.test;

import static org.hamcrest.CoreMatchers.either;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

Expand Down Expand Up @@ -141,6 +144,14 @@ public static Class<?> getLocationType(Location location) {
}
}

public static void assumeExtLayout() {
Shape shape = Shape.newBuilder().build();
assertThat("Unexpected Shape class name (the assertion may need to be updated if the code is refactored)",
shape.getClass().getName(), either(endsWith("ShapeExt")).or(endsWith("ShapeBasic")));
Assume.assumeTrue("Test is specific to the Extended Dynamic Object Layout",
shape.getClass().getName().endsWith("ShapeExt"));
}

public static Location assumeCoreLocation(Location location) {
Assume.assumeTrue(isCoreLocation(location));
return location;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
*/
package com.oracle.truffle.object.ext.test;

import static com.oracle.truffle.object.basic.test.DOTestAsserts.assumeExtLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
Expand All @@ -54,7 +56,6 @@
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.object.ext.test.ObjectModelRegressionTest.TestDynamicObject;
import com.oracle.truffle.tck.tests.TruffleTestAssumptions;

public class GR42603 {

Expand All @@ -63,7 +64,7 @@ public class GR42603 {

@Test
public void testReplacePropertyRace() throws Throwable {
TruffleTestAssumptions.assumeEnterpriseRuntime();
assumeExtLayout();
for (int i = 0; i < 100; i++) {
testConcurrentReplaceProperty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
*/
package com.oracle.truffle.object.ext.test;

import static com.oracle.truffle.object.basic.test.DOTestAsserts.assumeExtLayout;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.getTypeAssumption;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.getTypeAssumptionRecord;
import static org.junit.Assert.assertFalse;
Expand All @@ -55,7 +56,6 @@
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.tck.tests.TruffleTestAssumptions;

public class GR52036 {

Expand All @@ -70,7 +70,7 @@ public class GR52036 {
@SuppressWarnings("try")
@Test
public void testGR52036Reproducer() throws Throwable {
TruffleTestAssumptions.assumeEnterpriseRuntime();
assumeExtLayout();

class ObjType1 extends DynamicObject {
protected ObjType1(Shape shape) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import static com.oracle.truffle.object.basic.test.DOTestAsserts.assertObjectLocation;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.assertPrimitiveLocation;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.assumeExtLayout;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.invokeGetter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
Expand All @@ -56,6 +57,8 @@
import java.util.List;
import java.util.Map;

import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand All @@ -67,7 +70,6 @@
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.test.AbstractParametrizedLibraryTest;
import com.oracle.truffle.tck.tests.TruffleTestAssumptions;

@SuppressWarnings("deprecation")
@RunWith(Parameterized.class)
Expand Down Expand Up @@ -386,7 +388,7 @@ public void testChangeFlagsConstantToNonConstant() {

@Test
public void testTryMergeShapes() {
TruffleTestAssumptions.assumeEnterpriseRuntime();
assumeExtLayout();

// Assume (MaxMergeDepth >= 5)
Shape emptyShape = Shape.newBuilder().allowImplicitCastIntToDouble(true).build();
Expand Down Expand Up @@ -437,7 +439,7 @@ public void testTryMergeShapes() {

@Test
public void testTryMergeShapes2() {
TruffleTestAssumptions.assumeEnterpriseRuntime();
assumeExtLayout();

// Assume (MaxMergeDepth >= 5 && MaxMergeDiff >= 2)

Expand Down Expand Up @@ -473,6 +475,25 @@ public void testTryMergeShapes2() {
assertSame(b.getShape(), a.getShape());
}

@Test
public void testBooleanLocationTypeAssumption() {
assumeExtLayout();

Shape emptyShape = Shape.newBuilder().build();

DynamicObject obj = new TestDynamicObject(emptyShape);

DynamicObjectLibrary library = createLibrary(DynamicObjectLibrary.class, obj);

library.put(obj, "b1", true);
library.put(obj, "b2", true);
library.put(obj, "b2", false);

Shape shape = obj.getShape();
MatcherAssert.assertThat(shape.getProperty("b1").getLocation().toString(), CoreMatchers.containsString("Boolean"));
MatcherAssert.assertThat(shape.getProperty("b2").getLocation().toString(), CoreMatchers.containsString("Boolean"));
}

/**
* Tests that onPropertyTransition is called by replace and remove property transitions.
*/
Expand Down Expand Up @@ -510,6 +531,132 @@ public void testPropertyAssumptionInvalidation() {
assertFalse(assumption.toString(), assumption.isValid());
}

/**
* Tests that property assumptions are blocked after remove property transitions.
*/
@Test
public void testPropertyAssumptionInvalidAfterRemove() {
Shape emptyShape = Shape.newBuilder().propertyAssumptions(true).build();

DynamicObject h1 = new TestDynamicObject(emptyShape);
DynamicObjectLibrary on = createLibrary(DynamicObjectLibrary.class, h1);
DynamicObjectLibrary off = createLibrary(DynamicObjectLibrary.class, h1);

// initialize caches
on.put(h1, "name", h1);
on.put(h1, "alias", h1);
off.removeKey(h1, "name");
off.removeKey(h1, "alias");

DynamicObject h2 = new TestDynamicObject(emptyShape);
// repeat on another object with cached transitions
on.put(h2, "name", h2);
on.put(h2, "alias", h2);

Assumption aliasAssumption = h2.getShape().getPropertyAssumption("alias");
assertFalse("Property assumption for 'alias' should already be invalid: " + aliasAssumption, aliasAssumption.isValid());

on.put(h2, "alias", h2);
off.removeKey(h2, "name");
off.removeKey(h2, "alias");
}

/**
* Tests that property assumptions are blocked after replace property transitions.
*/
@Test
public void testPropertyAssumptionInvalidAfterReplace1() {
assumeExtLayout();

Shape emptyShape = Shape.newBuilder().propertyAssumptions(true).build();

int flag = 2;
DynamicObject h1 = new TestDynamicObject(emptyShape);
DynamicObjectLibrary on = createLibrary(DynamicObjectLibrary.class, h1);
DynamicObjectLibrary off = createLibrary(DynamicObjectLibrary.class, h1);

// initialize caches
on.put(h1, "name", h1);
on.put(h1, "alias", h1);
off.setPropertyFlags(h1, "name", flag);
off.setPropertyFlags(h1, "alias", flag);

DynamicObject h2 = new TestDynamicObject(emptyShape);
// repeat cached operations on another object
on.put(h2, "name", h2);
on.put(h2, "alias", h2);

Assumption aliasAssumption = h2.getShape().getPropertyAssumption("alias");
assertFalse("Property assumption for 'alias' should already be invalid: " + aliasAssumption, aliasAssumption.isValid());

on.put(h2, "alias", h2);
off.setPropertyFlags(h2, "name", flag);
off.setPropertyFlags(h2, "alias", flag);

assertEquals(flag, h2.getShape().getProperty("name").getFlags());
assertEquals(flag, h2.getShape().getProperty("alias").getFlags());
}

/**
* Tests that property assumptions are blocked after replace property transitions.
*/
@Test
public void testPropertyAssumptionInvalidAfterReplace2() {
assumeExtLayout();

Shape emptyShape = Shape.newBuilder().propertyAssumptions(true).build();

int flag = 2;
DynamicObject h1 = new TestDynamicObject(emptyShape);
DynamicObjectLibrary on = createLibrary(DynamicObjectLibrary.class, h1);
DynamicObjectLibrary off = createLibrary(DynamicObjectLibrary.class, h1);

// initialize caches
on.put(h1, "name", h1);
on.put(h1, "alias", h1);
off.putWithFlags(h1, "name", h1, flag);
off.putWithFlags(h1, "alias", h1, flag);

DynamicObject h2 = new TestDynamicObject(emptyShape);
// repeat cached operations on another object
on.put(h2, "name", h2);
on.put(h2, "alias", h2);

Assumption aliasAssumption = h2.getShape().getPropertyAssumption("alias");
assertFalse("Property assumption for 'alias' should already be invalid: " + aliasAssumption, aliasAssumption.isValid());

on.put(h2, "alias", h2);
off.putWithFlags(h2, "name", h2, flag);
off.putWithFlags(h2, "alias", h2, flag);

assertEquals(flag, h2.getShape().getProperty("name").getFlags());
assertEquals(flag, h2.getShape().getProperty("alias").getFlags());
}

/**
* Tests that property assumptions are invalid after value type transitions.
*/
@Test
public void testPropertyAssumptionInvalidAfterTypeTransition() {
Shape emptyShape = Shape.newBuilder().propertyAssumptions(true).build();

DynamicObject h1 = new TestDynamicObject(emptyShape);
DynamicObjectLibrary lib = createLibrary(DynamicObjectLibrary.class, h1);

// initialize caches
lib.put(h1, "name", 42);
lib.put(h1, "alias", 43);

Assumption aliasAssumption = h1.getShape().getPropertyAssumption("alias");

DynamicObject h2 = new TestDynamicObject(emptyShape);
// repeat cached operations on another object
lib.put(h2, "name", 42);
lib.put(h2, "alias", h1);

assertFalse("Property assumption for 'alias' should be invalid: " + aliasAssumption, aliasAssumption.isValid());
}

static class TestDynamicObject extends DynamicObject {
protected TestDynamicObject(Shape shape) {
super(shape);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import static com.oracle.truffle.object.basic.test.DOTestAsserts.assertObjectLocation;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.assertPrimitiveLocation;
import static com.oracle.truffle.object.basic.test.DOTestAsserts.assumeExtLayout;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
Expand All @@ -61,7 +62,6 @@
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.test.AbstractParametrizedLibraryTest;
import com.oracle.truffle.object.ext.test.ObjectModelRegressionTest.TestDynamicObject;
import com.oracle.truffle.tck.tests.TruffleTestAssumptions;

@SuppressWarnings("deprecation")
@RunWith(Parameterized.class)
Expand All @@ -86,7 +86,7 @@ private static DynamicObject newInstance(Shape emptyShape) {

@Before
public void before() {
TruffleTestAssumptions.assumeEnterpriseRuntime();
assumeExtLayout();
}

@Test
Expand Down
Loading