Skip to content

Commit 3f079a0

Browse files
committed
[GR-64086] Add extended dynamic object layout.
PullRequest: graal/20465
2 parents 92b2647 + 76c0d49 commit 3f079a0

File tree

99 files changed

+8282
-2397
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+8282
-2397
lines changed

compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/TruffleRuntimeTest.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,15 +29,16 @@
2929
import static org.junit.Assert.assertNull;
3030
import static org.junit.Assert.assertTrue;
3131

32-
import jdk.graal.compiler.api.test.Graal;
33-
import jdk.graal.compiler.runtime.RuntimeProvider;
3432
import org.junit.Test;
3533

3634
import com.oracle.truffle.api.Truffle;
3735
import com.oracle.truffle.api.TruffleRuntime;
3836
import com.oracle.truffle.api.impl.DefaultTruffleRuntime;
3937
import com.oracle.truffle.api.impl.TVMCI;
4038

39+
import jdk.graal.compiler.api.test.Graal;
40+
import jdk.graal.compiler.runtime.RuntimeProvider;
41+
4142
public class TruffleRuntimeTest {
4243

4344
@Test
@@ -75,12 +76,4 @@ public void testGetCapabilityObjectClass() {
7576
assertNull("Expected null return value for Object.class", object);
7677
}
7778

78-
@SuppressWarnings("deprecation")
79-
@Test
80-
public void testGetLayoutFactory() {
81-
TruffleRuntime runtime = Truffle.getRuntime();
82-
com.oracle.truffle.api.object.LayoutFactory layoutFactory = runtime.getCapability(com.oracle.truffle.api.object.LayoutFactory.class);
83-
assertNotNull("LayoutFactory not found", layoutFactory);
84-
// Rely on modules to only load trusted service providers
85-
}
8679
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/KnownTruffleTypes.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -125,7 +125,7 @@ public class KnownTruffleTypes extends AbstractKnownTruffleTypes {
125125
// truffle.api.object
126126
public final ResolvedJavaType Shape = lookupType("com.oracle.truffle.api.object.Shape");
127127
public final ResolvedJavaType DynamicObject = lookupType("com.oracle.truffle.api.object.DynamicObject");
128-
public final ResolvedJavaType UnsafeAccess = lookupType("com.oracle.truffle.object.UnsafeAccess");
128+
public final ResolvedJavaType UnsafeAccess = lookupType("com.oracle.truffle.api.object.UnsafeAccess");
129129

130130
// truffle.api.string
131131
public final ResolvedJavaType TruffleString = lookupType("com.oracle.truffle.api.strings.TruffleString");

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/substitutions/TruffleGraphBuilderPlugins.java

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
import jdk.graal.compiler.options.OptionType;
101101
import jdk.graal.compiler.phases.util.Providers;
102102
import jdk.graal.compiler.replacements.StandardGraphBuilderPlugins;
103+
import jdk.graal.compiler.replacements.arraycopy.ArrayCopySnippets;
103104
import jdk.graal.compiler.replacements.nodes.arithmetic.UnsignedMulHighNode;
104105
import jdk.graal.compiler.serviceprovider.SpeculationReasonGroup;
105106
import jdk.graal.compiler.truffle.KnownTruffleTypes;
@@ -133,6 +134,7 @@
133134
import jdk.vm.ci.meta.JavaConstant;
134135
import jdk.vm.ci.meta.JavaKind;
135136
import jdk.vm.ci.meta.MetaAccessProvider;
137+
import jdk.vm.ci.meta.ResolvedJavaField;
136138
import jdk.vm.ci.meta.ResolvedJavaMethod;
137139
import jdk.vm.ci.meta.ResolvedJavaType;
138140
import jdk.vm.ci.meta.SpeculationLog;
@@ -167,7 +169,7 @@ public static void registerInvocationPlugins(InvocationPlugins plugins, KnownTru
167169
registerFrameWithoutBoxingPlugins(plugins, types, canDelayIntrinsification);
168170
registerTruffleSafepointPlugins(plugins, types, canDelayIntrinsification);
169171
registerNodePlugins(plugins, types, metaAccess, canDelayIntrinsification, providers.getConstantReflection());
170-
registerDynamicObjectPlugins(plugins, types, canDelayIntrinsification);
172+
registerDynamicObjectPlugins(plugins, types, canDelayIntrinsification, providers.getConstantReflection());
171173
registerBufferPlugins(plugins, types, canDelayIntrinsification);
172174
registerMemorySegmentPlugins(plugins, types, canDelayIntrinsification);
173175
}
@@ -1111,9 +1113,83 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
11111113
}
11121114
}
11131115

1114-
private static void registerDynamicObjectPlugins(InvocationPlugins plugins, KnownTruffleTypes types, boolean canDelayIntrinsification) {
1116+
private static void registerDynamicObjectPlugins(InvocationPlugins plugins, KnownTruffleTypes types,
1117+
boolean canDelayIntrinsification, ConstantReflectionProvider constantReflection) {
1118+
if (!types.UnsafeAccess.isInitialized()) {
1119+
types.UnsafeAccess.initialize();
1120+
}
1121+
1122+
ResolvedJavaField[] staticFields = types.UnsafeAccess.getStaticFields();
1123+
JavaConstant anyConstant = null;
1124+
for (ResolvedJavaField field : staticFields) {
1125+
if (field.getName().equals("ANY_LOCATION")) {
1126+
anyConstant = constantReflection.readFieldValue(field, null);
1127+
break;
1128+
}
1129+
}
1130+
1131+
JavaKind[] usedJavaKinds = {JavaKind.Boolean, JavaKind.Byte, JavaKind.Int, JavaKind.Short, JavaKind.Long, JavaKind.Float, JavaKind.Double, JavaKind.Object};
1132+
11151133
Registration r = new Registration(plugins, new ResolvedJavaSymbol(types.UnsafeAccess));
1116-
registerUnsafeLoadStorePlugins(r, canDelayIntrinsification, null, JavaKind.Long);
1134+
registerUnsafeLoadStorePlugins(r, canDelayIntrinsification, anyConstant, usedJavaKinds);
1135+
registerUnsafeCast(r, types, canDelayIntrinsification);
1136+
registerBooleanCast(r);
1137+
registerArrayCopy(r);
1138+
1139+
registerDynamicObjectShapePlugins(plugins, types, canDelayIntrinsification);
1140+
}
1141+
1142+
private static void registerDynamicObjectShapePlugins(InvocationPlugins plugins, KnownTruffleTypes types, boolean canDelayIntrinsification) {
1143+
ResolvedJavaType dynamicObjectType = types.DynamicObject;
1144+
ResolvedJavaType shapeType = types.Shape;
1145+
ResolvedJavaSymbol dynamicObjectSymbol = new ResolvedJavaSymbol(dynamicObjectType);
1146+
ResolvedJavaSymbol shapeSymbol = new ResolvedJavaSymbol(shapeType);
1147+
Registration r = new Registration(plugins, dynamicObjectSymbol);
1148+
r.register(new RequiredInvocationPlugin("getShapeHelper", shapeSymbol) {
1149+
@Override
1150+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode shape) {
1151+
Stamp piStamp = StampFactory.object(TypeReference.createTrusted(b.getAssumptions(), shapeType), true);
1152+
ValueNode piNode = PiNode.create(shape, piStamp);
1153+
b.addPush(JavaKind.Object, piNode);
1154+
return true;
1155+
}
1156+
});
1157+
r.register(new RequiredInvocationPlugin("setShapeHelper", Receiver.class, shapeSymbol, long.class) {
1158+
@Override
1159+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode shape, ValueNode shapeOffset) {
1160+
if (canDelayIntrinsification) {
1161+
return false;
1162+
}
1163+
if (!shapeOffset.isConstant()) {
1164+
return false;
1165+
}
1166+
LocationIdentity locationIdentity = LocationIdentity.any();
1167+
boolean forceAnyLocation = true;
1168+
b.add(new RawStoreNode(receiver.get(true), shapeOffset, shape, JavaKind.Object, locationIdentity, true, null, forceAnyLocation));
1169+
return true;
1170+
}
1171+
});
1172+
}
1173+
1174+
private static void registerBooleanCast(Registration r) {
1175+
r.register(new RequiredInvocationPlugin("booleanCast", int.class) {
1176+
@Override
1177+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
1178+
b.addPush(JavaKind.Boolean, value);
1179+
return true;
1180+
}
1181+
});
1182+
r.register(new RequiredInvocationPlugin("intCast", boolean.class) {
1183+
@Override
1184+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
1185+
b.addPush(JavaKind.Int, value);
1186+
return true;
1187+
}
1188+
});
1189+
}
1190+
1191+
private static void registerArrayCopy(Registration r) {
1192+
ArrayCopySnippets.registerSystemArraycopyPlugin(r, true);
11171193
}
11181194

11191195
public static void registerUnsafeCast(Registration r, KnownTruffleTypes types, boolean canDelayIntrinsification) {

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,6 @@ public void cleanup() {
476476
invokeStaticMethod("com.oracle.truffle.api.library.LibraryFactory", "resetNativeImageState",
477477
Collections.singletonList(ClassLoader.class), imageClassLoader);
478478
invokeStaticMethod("com.oracle.truffle.api.source.Source", "resetNativeImageState", Collections.emptyList());
479-
// clean up cached object layouts
480-
invokeStaticMethod("com.oracle.truffle.object.LayoutImpl", "resetNativeImageState", Collections.emptyList());
481479
}
482480

483481
@Override
@@ -583,8 +581,8 @@ public void duringSetup(DuringSetupAccess a) {
583581
metaAccess = access.getMetaAccess();
584582

585583
uncachedDispatchField = access.findField(LibraryFactory.class, "uncachedDispatch");
586-
layoutInfoMapField = access.findField("com.oracle.truffle.object.DefaultLayout$LayoutInfo", "LAYOUT_INFO_MAP");
587-
layoutMapField = access.findField("com.oracle.truffle.object.DefaultLayout", "LAYOUT_MAP");
584+
layoutInfoMapField = access.findField("com.oracle.truffle.api.object.LayoutImpl", "LAYOUT_INFO_MAP");
585+
layoutMapField = access.findField("com.oracle.truffle.api.object.LayoutImpl", "LAYOUT_MAP");
588586
libraryFactoryCacheField = access.findField("com.oracle.truffle.api.library.LibraryFactory$ResolvedDispatch", "CACHE");
589587
if (Options.TruffleCheckPreinitializedFiles.getValue()) {
590588
var classInitializationSupport = access.getHostVM().getClassInitializationSupport();
@@ -970,7 +968,7 @@ private static void initializeDynamicObjectLayoutImpl(Class<?> javaClass) {
970968
} catch (IllegalAccessException e) {
971969
throw VMError.shouldNotReachHere(e);
972970
}
973-
invokeStaticMethod("com.oracle.truffle.object.LayoutImpl", "initializeDynamicObjectLayout", List.of(Class.class, MethodHandles.Lookup.class), javaClass, privateLookup);
971+
invokeStaticMethod("com.oracle.truffle.api.object.LayoutImpl", "initializeDynamicObjectLayout", List.of(Class.class, MethodHandles.Lookup.class), javaClass, privateLookup);
974972
}
975973

976974
private static void registerDynamicObjectFields(BeforeAnalysisAccessImpl config) {
@@ -1578,14 +1576,8 @@ static void logFallback(String message) {
15781576
}
15791577
}
15801578

1581-
@TargetClass(className = "com.oracle.truffle.object.CoreLocations$DynamicObjectFieldLocation", onlyWith = TruffleBaseFeature.IsEnabled.class)
1582-
final class Target_com_oracle_truffle_object_CoreLocations_DynamicObjectFieldLocation {
1583-
@Alias @RecomputeFieldValue(kind = Kind.AtomicFieldUpdaterOffset) //
1584-
private long offset;
1585-
}
1586-
1587-
@TargetClass(className = "com.oracle.truffle.object.CoreLocations$DynamicLongFieldLocation", onlyWith = TruffleBaseFeature.IsEnabled.class)
1588-
final class Target_com_oracle_truffle_object_CoreLocations_DynamicLongFieldLocation {
1579+
@TargetClass(className = "com.oracle.truffle.api.object.FieldInfo", onlyWith = TruffleBaseFeature.IsEnabled.class)
1580+
final class Target_com_oracle_truffle_api_object_FieldInfo {
15891581
@Alias @RecomputeFieldValue(kind = Kind.AtomicFieldUpdaterOffset) //
15901582
private long offset;
15911583
}

truffle/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ This changelog summarizes major changes between Truffle versions relevant to lan
1717
* GR-64533 By default every specialization is now included for {@link GenerateUncached}, except specializations that require a {@link Specialization#limit() limit} and are replaced, those are excluded by default. By setting `@Specialization(excludeForUncached=..)` explicitly the default behavior can be overridden, e.g. to include or exclude a specialization for uncached. Specializations which are no longer compatible with uncached will produce a warning instead of an error for compatibility reasons until all languages are migrated. It is therefore expected that language implementations may see new warnings with this version.
1818
* GR-64124 Added `BytecodeOSRNode.pollOSRBackEdge(BytecodeOSRNode, int)` that supports batch polling for bytecode OSR. Using this method avoids checking for bytecode OSR on every loop backedge.
1919
* GR-64124 Deprecated `BytecodeOSRNode.pollOSRBackEdge(BytecodeOSRNode)`. Use `BytecodeOSRNode.pollOSRBackEdge(BytecodeOSRNode, int)` instead. Please note that the old method did call `TruffleSafepoint.poll(Node)`, but the the new method does not. Please double check that your bytecode interpreter polls Truffle safepoints at loop back-edges.
20+
* GR-64086 Added extended Dynamic Object Model Layout that adds:
21+
* A shape obsolescence strategy enabling optimistic type speculation for primitive property values with gradual migration to more general shapes on speculation failure (moving primitive slots to reference slots), eventually converging on a general enough shape tree. Reduces shape polymorphism by obsoleting and merging too specific shapes in favor of more general shapes.
22+
* Automatic reference type tracking based on assumptions, eliminating redundant type checks.
23+
* Automatic single-assignment tracking based on assumptions allowing languages to assume that a property is effectively final (i.e. stays unchanged after the initial assignment) as well as constant-fold values of a constant receiver with a known shape.
24+
* You can still disable the new layout and switch back to the previous implementation using the system property: `-Dtruffle.object.LayoutFactory=com.oracle.truffle.api.object.CoreLayoutFactory`.
2025

2126
## Version 24.2.0
2227
* GR-60636 Truffle now stops compiling when the code cache fills up on HotSpot. A warning is printed when that happens.

truffle/mx.truffle/suite.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@
658658
"sourceDirs" : ["src"],
659659
"dependencies" : [
660660
"com.oracle.truffle.api.interop",
661+
"com.oracle.truffle.object",
661662
],
662663
"requires" : [
663664
"jdk.unsupported", # sun.misc.Unsafe
@@ -789,22 +790,19 @@
789790
"com.oracle.truffle.object" : {
790791
"subDir" : "src",
791792
"sourceDirs" : ["src"],
792-
"dependencies" : ["com.oracle.truffle.api.object"],
793-
"requires" : [
794-
"jdk.unsupported", # sun.misc.Unsafe
795-
],
793+
"dependencies" : ["com.oracle.truffle.api"],
796794
"checkstyle" : "com.oracle.truffle.api",
797795
"javaCompliance" : "17+",
798-
"annotationProcessors" : ["TRUFFLE_DSL_PROCESSOR"],
796+
"annotationProcessors" : [],
799797
"workingSets" : "Truffle",
800798
"graalCompilerSourceEdition": "ignore",
801799
},
802800

803-
"com.oracle.truffle.object.basic.test" : {
801+
"com.oracle.truffle.api.object.test" : {
804802
"subDir" : "src",
805803
"sourceDirs" : ["src"],
806804
"dependencies" : [
807-
"com.oracle.truffle.object",
805+
"com.oracle.truffle.api.object",
808806
"com.oracle.truffle.api.test",
809807
"mx:JUNIT"
810808
],
@@ -1635,7 +1633,6 @@
16351633
],
16361634
"uses" : [
16371635
"com.oracle.truffle.api.impl.TruffleLocator",
1638-
"com.oracle.truffle.api.object.LayoutFactory",
16391636
"com.oracle.truffle.runtime.LoopNodeFactory",
16401637
"com.oracle.truffle.runtime.TruffleTypes",
16411638
"com.oracle.truffle.runtime.EngineCacheSupport",
@@ -1724,6 +1721,8 @@
17241721
# Qualified exports
17251722
"com.oracle.truffle.api.impl to org.graalvm.locator, org.graalvm.truffle.runtime, com.oracle.truffle.enterprise, org.graalvm.truffle.runtime.svm, com.oracle.truffle.enterprise.svm, com.oracle.truffle.truffle_nfi_panama",
17261723
"com.oracle.truffle.object to com.oracle.truffle.enterprise, org.graalvm.truffle.runtime, com.oracle.truffle.enterprise, org.graalvm.truffle.runtime.svm, com.oracle.truffle.enterprise.svm",
1724+
"com.oracle.truffle.object.enterprise to com.oracle.truffle.enterprise",
1725+
# GR-64984: Exports to com.oracle.truffle.enterprise are only needed for jdk21.
17271726
],
17281727
"opens" : [
17291728
"com.oracle.truffle.polyglot to org.graalvm.truffle.runtime",
@@ -1765,7 +1764,7 @@
17651764
"com.oracle.truffle.api.profiles",
17661765
"com.oracle.truffle.api.debug",
17671766
"com.oracle.truffle.api.utilities",
1768-
"com.oracle.truffle.object",
1767+
"com.oracle.truffle.api.object",
17691768
"com.oracle.truffle.api.strings",
17701769
"com.oracle.truffle.polyglot",
17711770
"com.oracle.truffle.host",
@@ -2201,7 +2200,7 @@
22012200
"com.oracle.truffle.api.debug.test",
22022201
"com.oracle.truffle.api.strings.test",
22032202
"com.oracle.truffle.api.bytecode.test",
2204-
"com.oracle.truffle.object.basic.test",
2203+
"com.oracle.truffle.api.object.test",
22052204
"com.oracle.truffle.api.staticobject.test",
22062205
],
22072206
"exclude" : [

truffle/src/com.oracle.truffle.api.library/src/com/oracle/truffle/api/library/GenerateLibrary.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -89,7 +89,7 @@
8989
* receiver types of third parties or the JDK. For example the Truffle interop library has default
9090
* exports for most {@link Number} types, {@link String} and {@link Boolean} type.
9191
* <p>
92-
* In order to enable AOT generation for a a library annotate the class with {@link GenerateAOT} and
92+
* In order to enable AOT generation for a library annotate the class with {@link GenerateAOT} and
9393
* enable exports to be used for AOT by setting {@link ExportLibrary#useForAOT()} to
9494
* <code>true</code>.
9595
*
@@ -326,7 +326,7 @@
326326
boolean defaultExportLookupEnabled() default false;
327327

328328
/**
329-
* Allows the use of {@link DynamicDispatchLibrary} with this library. By default dynamic
329+
* Allows the use of {@link DynamicDispatchLibrary} with this library. By default, dynamic
330330
* dispatch is enabled. If this flag is set to <code>false</code> then the
331331
* {@link DynamicDispatchLibrary#dispatch(Object) dispatch} method will not be used for this
332332
* library. Only default exports and exports declared with the receiver type will be used
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0

0 commit comments

Comments
 (0)