Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
921aa67
[GR-36894] Add nodes for DynamicObject
eregon Sep 18, 2025
9b781e2
Wrap DynamicObjectLibrary for tests and fix visibility.
woess Oct 3, 2025
bb975e8
Add DynamicObject benchmarks for primitive get and set and field access.
woess Oct 13, 2025
3c3b90b
No need to enter a context for DynamicObject benchmarking.
woess Oct 31, 2025
6a56eae
Rename getOrDefault to execute.
woess Nov 4, 2025
312226e
Rename put to execute and add InliningRoot annotation.
woess Nov 4, 2025
33c7f56
Remove unsafeCast without exact parameter.
woess Oct 16, 2025
d4b3d69
Initialize extension arrays with empty array constant instead of null.
woess Oct 8, 2025
bb3e0ed
Refactor Location classes.
woess Oct 15, 2025
f3399cf
Use final Location get and set.
woess Oct 28, 2025
9e0776b
Remove unused SomSupport.
woess Oct 16, 2025
4de8fab
Unify condition anchor handling.
woess Nov 7, 2025
8a41b5a
Add UnsafeAccess.hostUnsafeCast and mark extension arrays as non-null.
woess Oct 17, 2025
d2b501b
Add tests for PutNode.executeIfAbsent and executeWithFlagsIfPresent.
woess Nov 6, 2025
754b643
Use one PutNode per property in CopyPropertiesNode.
woess Nov 6, 2025
850bd4a
Revise PutNode implementation.
woess Nov 6, 2025
75c6c6d
Remove HasShapeFlagsNode.
woess Nov 4, 2025
1b9f51a
Remove AddShapeFlagsNode.
woess Nov 4, 2025
f69c446
Simplify SetShapeFlagsNode.
woess Nov 4, 2025
a6e2daf
Make store fence unconditional in the interpreter to avoid shared sha…
woess Nov 6, 2025
2f76e7d
Use a common read/write for object locations.
woess Nov 7, 2025
e6cf92d
Throw UnexpectedResultException for boxed values, too.
woess Nov 7, 2025
5a629b0
Always clear the source location when moving locations.
woess Nov 10, 2025
b964096
Add system property for shape/key cache limit.
woess Nov 10, 2025
36c0c97
Improve DynamicObject javadoc.
woess Nov 10, 2025
36d6c3e
Add condition profile.
woess Nov 10, 2025
ffac214
Fix Truffle DSL not honoring `@SuppressWarnings("deprecation")`.
woess Nov 10, 2025
52bb34b
Deprecate DynamicObjectLibrary.
woess Nov 10, 2025
58ef697
Update truffle sigtest snapshot.
woess Oct 3, 2025
147f8c1
Remove VarHandle-based field access.
woess Nov 10, 2025
ecab15b
Simplify putGeneric and use setInternal.
woess Nov 10, 2025
ec2d80c
Hoist index read.
woess Nov 11, 2025
3dffe98
Omit receiver type check.
woess Nov 10, 2025
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().execute(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().execute(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.execute(obj, "key", (int) arg1);
}
int val;
while (true) {
val = getInt(obj, "key");
if (val >= 42) {
break;
}
dynamicObjectLibrary.put(obj, "key", val + 2);
putNode.execute(obj, "key", val + 2);
}
return val;
}

private int getInt(DynamicObject obj, Object key) {
try {
return dynamicObjectLibrary.getIntOrDefault(obj, key, null);
return getNode.executeInt(obj, key, null);
} catch (UnexpectedResultException e) {
throw CompilerDirectives.shouldNotReachHere();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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 @@ -29,18 +29,34 @@
import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_0;
import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_0;

import jdk.graal.compiler.core.common.calc.CanonicalCondition;
import jdk.graal.compiler.core.common.type.StampFactory;
import jdk.graal.compiler.graph.Node;
import jdk.graal.compiler.graph.NodeClass;
import jdk.graal.compiler.nodeinfo.NodeInfo;
import jdk.graal.compiler.nodeinfo.Verbosity;
import jdk.graal.compiler.nodes.calc.CompareNode;
import jdk.graal.compiler.nodes.extended.GuardingNode;
import jdk.graal.compiler.nodes.extended.ValueAnchorNode;
import jdk.graal.compiler.nodes.spi.Canonicalizable;
import jdk.graal.compiler.nodes.spi.CanonicalizerTool;
import jdk.graal.compiler.nodes.spi.Lowerable;
import jdk.graal.compiler.nodes.spi.LoweringTool;
import jdk.graal.compiler.options.OptionValues;
import jdk.vm.ci.meta.ConstantReflectionProvider;
import jdk.vm.ci.meta.MetaAccessProvider;

/**
* A {@link ConditionAnchorNode} is used to anchor a floatable unsafe load or {@linkplain PiNode
* unsafe cast} in the control flow and associate it with a control flow dependency (i.e. a guard),
* represented as a boolean condition. Conditional Elimination then tries to find a guard that
* corresponds to this condition, and rewires the condition anchor's usages to that guard. If no
* such relationship can be established, the condition anchor is replaced with an unconditional
* {@link ValueAnchorNode}.
*
* @see jdk.graal.compiler.phases.common.ConditionalEliminationPhase
* @see jdk.graal.compiler.nodes.extended.GuardedUnsafeLoadNode
*/
@NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})", allowedUsageTypes = Guard, cycles = CYCLES_0, size = SIZE_0)
public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable.Unary<Node>, Lowerable, GuardingNode {

Expand All @@ -58,6 +74,37 @@ public ConditionAnchorNode(LogicNode condition, boolean negated) {
this.condition = condition;
}

/**
* Creates a condition anchor from a boolean value representing the guarding condition.
*
* Note: The caller must handle the case where no anchor is needed for constant true.
*/
public static FixedWithNextNode create(ValueNode condition, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, NodeView view) {
if (condition.isConstant()) {
return new ValueAnchorNode();
} else {
return create(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, condition, ConstantNode.forBoolean(true), view));
}
}

/**
* Creates a condition anchor from a logical comparison.
*
* @see #canonical(CanonicalizerTool, Node)
*/
public static FixedWithNextNode create(LogicNode compareNode) {
if (compareNode instanceof LogicConstantNode) {
/*
* Even if the condition is true, an anchor that has usages must still exist since it's
* possible the condition is true for control flow reasons so the Pi stamp is also only
* valid for those reasons.
*/
return new ValueAnchorNode();
} else {
return new ConditionAnchorNode(compareNode);
}
}

public LogicNode condition() {
return condition;
}
Expand All @@ -77,14 +124,12 @@ public String toString(Verbosity verbosity) {

@Override
public Node canonical(CanonicalizerTool tool, Node forValue) {
if (forValue instanceof LogicNegationNode) {
LogicNegationNode negation = (LogicNegationNode) forValue;
if (forValue instanceof LogicNegationNode negation) {
return new ConditionAnchorNode(negation.getValue(), !negated);
}
if (forValue instanceof LogicConstantNode) {
LogicConstantNode c = (LogicConstantNode) forValue;
if (forValue instanceof LogicConstantNode c) {
// An anchor that still has usages must still exist since it's possible the condition is
// true for control flow reasons so the Pi stamp is also only valid for those reason.
// true for control flow reasons so the Pi stamp is also only valid for those reasons.
if (c.getValue() == negated || hasUsages()) {
return new ValueAnchorNode();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import com.oracle.truffle.compiler.TruffleCompilationTask;

import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.core.common.calc.CanonicalCondition;
import jdk.graal.compiler.core.common.memory.MemoryOrderMode;
import jdk.graal.compiler.core.common.type.IntegerStamp;
import jdk.graal.compiler.core.common.type.ObjectStamp;
Expand All @@ -63,7 +62,6 @@
import jdk.graal.compiler.nodes.FixedGuardNode;
import jdk.graal.compiler.nodes.FrameState;
import jdk.graal.compiler.nodes.InvokeNode;
import jdk.graal.compiler.nodes.LogicConstantNode;
import jdk.graal.compiler.nodes.LogicNode;
import jdk.graal.compiler.nodes.NamedLocationIdentity;
import jdk.graal.compiler.nodes.NodeView;
Expand All @@ -72,7 +70,6 @@
import jdk.graal.compiler.nodes.StructuredGraph;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.ValuePhiNode;
import jdk.graal.compiler.nodes.calc.CompareNode;
import jdk.graal.compiler.nodes.calc.ConditionalNode;
import jdk.graal.compiler.nodes.calc.IntegerMulHighNode;
import jdk.graal.compiler.nodes.calc.RoundNode;
Expand Down Expand Up @@ -1216,6 +1213,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant());
if (javaType == null) {
b.push(JavaKind.Object, object);
return true;
} else {
TypeReference type;
if (isExactType.asJavaConstant().asInt() != 0) {
Expand All @@ -1227,30 +1225,14 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec

boolean trustedNonNull = nonNull.asJavaConstant().asInt() != 0 && Options.TruffleTrustedNonNullCast.getValue(b.getOptions());
Stamp piStamp = StampFactory.object(type, trustedNonNull);

ConditionAnchorNode valueAnchorNode = null;
if (condition.isConstant() && condition.asJavaConstant().asInt() == 1) {
// Nothing to do.
} else {
boolean skipAnchor = false;
LogicNode compareNode = CompareNode.createCompareNode(object.graph(), CanonicalCondition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection,
NodeView.DEFAULT);

if (compareNode instanceof LogicConstantNode) {
LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode;
if (logicConstantNode.getValue()) {
skipAnchor = true;
}
}

if (!skipAnchor) {
valueAnchorNode = b.add(new ConditionAnchorNode(compareNode));
}
ValueNode guard = null;
// If the condition is the constant true then no guard is needed
if (!condition.isConstant() || condition.asJavaConstant().asInt() == 0) {
guard = b.add(ConditionAnchorNode.create(condition, constantReflection, b.getMetaAccess(), b.getOptions(), NodeView.DEFAULT));
}

b.addPush(JavaKind.Object, trustedBox(type, types, PiNode.create(object, piStamp, valueAnchorNode)));
b.addPush(JavaKind.Object, trustedBox(type, types, PiNode.create(object, piStamp, guard)));
return true;
}
return true;
} else if (canDelayIntrinsification) {
return false;
} else {
Expand Down Expand Up @@ -1308,9 +1290,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
ValueNode guard = null;
// If the condition is the constant true then no guard is needed
if (!condition.isConstant() || condition.asJavaConstant().asInt() == 0) {
LogicNode compare = b.add(CompareNode.createCompareNode(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, CanonicalCondition.EQ, condition,
ConstantNode.forBoolean(true, object.graph()), NodeView.DEFAULT));
guard = b.add(new ConditionAnchorNode(compare));
guard = b.add(ConditionAnchorNode.create(condition, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), NodeView.DEFAULT));
}
b.addPush(returnKind, b.add(new GuardedUnsafeLoadNode(b.addNonNullCast(object), offset, returnKind, locationIdentity, guard, forceLocation)));
return true;
Expand Down
Loading