diff --git a/common.json b/common.json
index 07a251a455ff5..38f6d23a3c5d2 100644
--- a/common.json
+++ b/common.json
@@ -14,9 +14,9 @@
"labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.9+9-jvmci-23.0-b22", "platformspecific": true },
"labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17.0.9+9-jvmci-23.0-b22-debug", "platformspecific": true },
"labsjdk-ce-17-llvm": {"name": "labsjdk", "version": "ce-17.0.9+9-jvmci-23.0-b22-sulong", "platformspecific": true },
- "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.9+11-jvmci-23.0-b21", "platformspecific": true },
- "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.9+11-jvmci-23.0-b21-debug", "platformspecific": true },
- "labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.9+11-jvmci-23.0-b21-sulong", "platformspecific": true },
+ "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.10+9-jvmci-23.0-b25", "platformspecific": true },
+ "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.10+9-jvmci-23.0-b25-debug", "platformspecific": true },
+ "labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.10+9-jvmci-23.0-b25-sulong", "platformspecific": true },
"oraclejdk19": {"name": "jpg-jdk", "version": "19", "build_id": "26", "release": true, "platformspecific": true, "extrabundles": ["static-libs"]},
"labsjdk-ce-19": {"name": "labsjdk", "version": "ce-19.0.1+10-jvmci-23.0-b04", "platformspecific": true },
diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py
index 638095a7cd309..65525ce100ffb 100644
--- a/compiler/mx.compiler/suite.py
+++ b/compiler/mx.compiler/suite.py
@@ -4,7 +4,7 @@
"sourceinprojectwhitelist" : [],
"groupId" : "org.graalvm.compiler",
- "version" : "23.0.2.2",
+ "version" : "23.0.3.0",
"release" : False,
"url" : "http://www.graalvm.org/",
"developer" : {
diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java
index 15b935770a25f..f1cc5b5328ef9 100644
--- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java
+++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java
@@ -26,6 +26,7 @@
// JaCoCo Exclude
+import org.graalvm.compiler.debug.GraalError;
import jdk.vm.ci.code.CodeUtil;
/**
@@ -258,4 +259,14 @@ public static byte[] hexStringToBytes(String hex) {
}
return bytes;
}
+
+ public static long addExact(long a, long b, int bits) {
+ if (bits == 32) {
+ return Math.addExact((int) a, (int) b);
+ } else if (bits == 64) {
+ return Math.addExact(a, b);
+ } else {
+ throw GraalError.shouldNotReachHere("Must be one of java's core datatypes int/long but is " + bits);
+ }
+ }
}
diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java
index c3d64a59838ad..db304041b0caf 100644
--- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java
+++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java
@@ -1095,7 +1095,7 @@ public boolean isNeutral(Constant value) {
}
},
- new BinaryOp.Sub(true, false) {
+ new BinaryOp.Sub(false, false) {
@Override
public Constant foldConstant(Constant const1, Constant const2) {
@@ -1487,7 +1487,7 @@ private long multiplyHighUnsigned(long x, long y, JavaKind javaKind) {
}
},
- new BinaryOp.Div(true, false) {
+ new BinaryOp.Div(false, false) {
@Override
public Constant foldConstant(Constant const1, Constant const2) {
diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java
index eff95e1b64675..e3d95e2aa202a 100644
--- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java
+++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java
@@ -32,8 +32,11 @@
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.Equivalence;
+
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.RetryableBailoutException;
import org.graalvm.compiler.core.common.calc.CanonicalCondition;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Graph.Mark;
@@ -776,6 +779,17 @@ public static boolean countedLoopExitConditionHasMultipleUsages(LoopEx loop) {
return condition.hasMoreThanOneUsage();
}
+ public static boolean strideAdditionOverflows(LoopEx loop) {
+ final int bits = ((IntegerStamp) loop.counted().getLimitCheckedIV().valueNode().stamp(NodeView.DEFAULT)).getBits();
+ long stride = loop.counted().getLimitCheckedIV().constantStride();
+ try {
+ NumUtil.addExact(stride, stride, bits);
+ return false;
+ } catch (ArithmeticException ae) {
+ return true;
+ }
+ }
+
public static boolean isUnrollableLoop(LoopEx loop) {
if (!loop.isCounted() || !loop.counted().getLimitCheckedIV().isConstantStride() || !loop.loop().getChildren().isEmpty() || loop.loopBegin().loopEnds().count() != 1 ||
loop.loopBegin().loopExits().count() > 1 || loop.counted().isInverted()) {
@@ -796,11 +810,8 @@ public static boolean isUnrollableLoop(LoopEx loop) {
if (countedLoopExitConditionHasMultipleUsages(loop)) {
return false;
}
- long stride = loop.counted().getLimitCheckedIV().constantStride();
- try {
- Math.addExact(stride, stride);
- } catch (ArithmeticException ae) {
- condition.getDebug().log(DebugContext.VERBOSE_LEVEL, "isUnrollableLoop %s doubling the stride overflows %d", loopBegin, stride);
+ if (strideAdditionOverflows(loop)) {
+ condition.getDebug().log(DebugContext.VERBOSE_LEVEL, "isUnrollableLoop %s doubling the stride overflows %d", loopBegin, loop.counted().getLimitCheckedIV().constantStride());
return false;
}
if (!loop.canDuplicateLoop()) {
diff --git a/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java b/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java
index ed7aa077a97bb..684ced3c42813 100644
--- a/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java
+++ b/compiler/src/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java
@@ -62,6 +62,7 @@
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
public class LoopPartialUnrollTest extends GraalCompilerTest {
@@ -392,4 +393,44 @@ public void testUsages() {
check = true;
}
+ static int rr = 0;
+
+ static int countedAfterSnippet(int i, int limit) {
+ int res = 0;
+ for (int j = i; GraalDirectives.injectIterationCount(1000, j <= limit); j += Integer.MAX_VALUE) {
+ rr += 42;
+ res += j;
+ }
+ return res;
+ }
+
+ SpeculationLog speculationLog;
+ boolean useSpeculationLog;
+
+ @Override
+ protected SpeculationLog getSpeculationLog() {
+ if (!useSpeculationLog) {
+ speculationLog = null;
+ return null;
+ }
+ if (speculationLog == null) {
+ speculationLog = getCodeCache().createSpeculationLog();
+ }
+ speculationLog.collectFailedSpeculations();
+ return speculationLog;
+ }
+
+ @Test
+ public void strideOverflow() {
+ check = false;
+ useSpeculationLog = true;
+ OptionValues opt = new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false);
+ for (int i = -1000; i < 1000; i++) {
+ for (int j = 0; j < 100; j++) {
+ test(opt, "countedAfterSnippet", i, j);
+ }
+ }
+ check = true;
+ useSpeculationLog = false;
+ }
}
diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java
index 73ebb3dfe68e5..19a04aad138ae 100644
--- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java
+++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java
@@ -48,7 +48,7 @@
import org.graalvm.compiler.nodes.extended.GuardedNode;
import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeValueMap;
-
+import org.graalvm.compiler.core.common.type.ArithmeticStamp;
import jdk.vm.ci.meta.Constant;
@NodeInfo(cycles = CYCLES_1, size = SIZE_1)
@@ -107,8 +107,7 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode for
* (cond ? 95 : 105)
*/
// @formatter:on
- return ConditionalNode.create(conditionalNode.condition, trueConstant,
- falseConstant, view);
+ return ConditionalNode.create(conditionalNode.condition, trueConstant, falseConstant, view);
}
}
}
@@ -249,7 +248,7 @@ private static ReassociateMatch findReassociate(BinaryArithmeticNode> parent,
}
private static boolean isReassociative(BinaryArithmeticNode> parent, ValueNode child) {
- if (!parent.isAssociative()) {
+ if (!parent.mayReassociate()) {
return false;
}
if (isNonExactAddOrSub(parent)) {
@@ -258,18 +257,50 @@ private static boolean isReassociative(BinaryArithmeticNode> parent, ValueNode
return child.getClass() == parent.getClass();
}
+ /**
+ * Determines whether this operation may be reassociated in the sense of
+ * {@link #reassociateUnmatchedValues} and {@link #reassociateMatchedValues}. These methods can
+ * perform transformations like {@code (a * 2) * b => (a * b) * 2}. In general, these
+ * transformations require the binary operation to be both {@linkplain BinaryOp#isAssociative()
+ * associative} to allow shifting of parentheses and {@linkplain BinaryOp#isCommutative()
+ * commutative} to allow changing the order of the operands.
+ *
+ * As a special case, subtraction on integers allows certain similar transformations, especially
+ * in expressions where it is mixed with addition. For example,
+ * {@link #reassociateUnmatchedValues} can transform {@code x + (C - y) -> (x - y) + C}, and
+ * {@link SubNode#canonical(CanonicalizerTool, ValueNode, ValueNode)} can transform
+ * {@code a - (a + b) -> -b}. Therefore this method returns {@code true} for integer
+ * subtraction. Users of this method must still check if the operation in question is
+ * subtraction and ensure that they only reassociate subtractions in sound ways. Floating-point
+ * subtraction does not permit such mathematically sound transformations due to rounding errors.
+ */
+ public boolean mayReassociate() {
+ return mayReassociate(getArithmeticOp(), stamp(NodeView.DEFAULT));
+ }
+
+ /**
+ * Determines whether the {@code op} may be reassociated in the sense of
+ * {@link #reassociateUnmatchedValues} and {@link #reassociateMatchedValues}.
+ *
+ * @see #mayReassociate()
+ */
+ public static boolean mayReassociate(BinaryOp> op, Stamp stamp) {
+ return (op.isAssociative() && op.isCommutative()) || (stamp.isIntegerStamp() && op.equals(((ArithmeticStamp) stamp).getOps().getSub()));
+ }
+
/**
* Tries to push down values which satisfy the criterion. This is an assistant function for
* {@linkplain BinaryArithmeticNode#reassociateMatchedValues} reassociateMatchedValues}. For
* example with a constantness criterion: {@code (a * 2) * b => (a * b) * 2}
*
- * This method accepts only {@linkplain BinaryOp#isAssociative() associative} operations such as
- * +, -, *, &, | and ^
+ * This method accepts only {@linkplain #mayReassociate() operations that allow reassociation}
+ * such as +, -, *, &, |, ^, min, and max.
*/
public static ValueNode reassociateUnmatchedValues(BinaryArithmeticNode> node, NodePredicate criterion, NodeView view) {
ValueNode forX = node.getX();
ValueNode forY = node.getY();
- assert node.getOp(forX, forY).isAssociative();
+ BinaryOp> op = node.getOp(forX, forY);
+ GraalError.guarantee(node.mayReassociate(), "%s: binary op %s does not satisfy precondition of reassociateUnmatchedValues", node, op);
// No need to re-associate if one of the operands has matched the criterion.
if (criterion.apply(forX) || criterion.apply(forY)) {
@@ -394,14 +425,15 @@ public static ValueNode reassociateUnmatchedValues(BinaryArithmeticNode> node,
* Tries to re-associate values which satisfy the criterion. For example with a constantness
* criterion: {@code (a + 2) + 1 => a + (1 + 2)}
*
- * This method accepts only {@linkplain BinaryOp#isAssociative() associative} operations such as
- * +, -, *, &, |, ^, min, max
+ * This method accepts only {@linkplain #mayReassociate() operations that allow reassociation}
+ * such as +, -, *, &, |, ^, min, and max.
*
* @param forY
* @param forX
*/
public static ValueNode reassociateMatchedValues(BinaryArithmeticNode> node, NodePredicate criterion, ValueNode forX, ValueNode forY, NodeView view) {
- assert node.getOp(forX, forY).isAssociative();
+ BinaryOp> op = node.getOp(forX, forY);
+ GraalError.guarantee(node.mayReassociate(), "%s: binary op %s does not satisfy precondition of reassociateMatchedValues", node, op);
ReassociateMatch match1 = findReassociate(node, criterion);
if (match1 == null) {
return node;
@@ -481,12 +513,6 @@ public static ValueNode reassociateMatchedValues(BinaryArithmeticNode> node, N
return MaxNode.create(a, MaxNode.create(m1, m2, view), view);
} else if (node instanceof MinNode) {
return MinNode.create(a, MinNode.create(m1, m2, view), view);
- } else if (node instanceof SignedFloatingIntegerDivNode) {
- return SignedFloatingIntegerDivNode.create(a, SignedFloatingIntegerDivNode.create(m1, m2, view, null, ((FloatingIntegerDivRemNode>) node).divisionOverflowIsJVMSCompliant()), view, null,
- ((FloatingIntegerDivRemNode>) node).divisionOverflowIsJVMSCompliant());
- } else if (node instanceof SignedFloatingIntegerRemNode) {
- return SignedFloatingIntegerRemNode.create(a, SignedFloatingIntegerRemNode.create(m1, m2, view, null, ((FloatingIntegerDivRemNode>) node).divisionOverflowIsJVMSCompliant()), view, null,
- ((FloatingIntegerDivRemNode>) node).divisionOverflowIsJVMSCompliant());
} else {
throw GraalError.shouldNotReachHere("unhandled node in reassociation with matched values: " + node); // ExcludeFromJacocoGeneratedReport
}
diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java
index d6233cab709d2..582232f8a48f0 100644
--- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java
+++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java
@@ -159,6 +159,9 @@ protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) {
if (result != null) {
return result;
}
+ if (!(forX.stamp(view) instanceof IntegerStamp)) {
+ return null;
+ }
// always prefer unsigned comparisons, however, if part of a graph we sometimes want to
// disable it for testing purposes
if (forX.getOptions() == null || GraalOptions.PreferUnsignedComparison.getValue(forX.getOptions())) {
diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java
index 63053733cffe3..e44309a8d542f 100644
--- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java
+++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SubNode.java
@@ -39,7 +39,6 @@
import org.graalvm.compiler.nodes.spi.CanonicalizerTool;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import org.graalvm.compiler.nodes.util.GraphUtil;
-
import jdk.vm.ci.meta.Constant;
import jdk.vm.ci.meta.PrimitiveConstant;
@@ -79,8 +78,8 @@ private static ValueNode canonical(SubNode subNode, BinaryOp op, Stamp stam
return ConstantNode.forPrimitive(stamp, zero);
}
}
- boolean associative = op.isAssociative();
- if (associative) {
+ boolean mayReassociate = BinaryArithmeticNode.mayReassociate(op, stamp);
+ if (mayReassociate) {
if (forX instanceof AddNode) {
AddNode x = (AddNode) forX;
if (x.getY() == forY) {
@@ -129,7 +128,7 @@ private static ValueNode canonical(SubNode subNode, BinaryOp op, Stamp stam
if (op.isNeutral(c)) {
return forX;
}
- if (associative && self != null) {
+ if (mayReassociate && self != null) {
ValueNode reassociated = reassociateMatchedValues(self, ValueNode.isConstantPredicate(), forX, forY, view);
if (reassociated != self) {
return reassociated;
@@ -153,7 +152,7 @@ private static ValueNode canonical(SubNode subNode, BinaryOp op, Stamp stam
*/
return NegateNode.create(forY, view);
}
- if (associative && self != null) {
+ if (mayReassociate && self != null) {
return reassociateMatchedValues(self, ValueNode.isConstantPredicate(), forX, forY, view);
}
}
diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java
index 13e798cfdb42c..a5052d7dc47c3 100644
--- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java
+++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopEx.java
@@ -231,7 +231,7 @@ public boolean reassociateInvariants() {
InvariantPredicate invariant = new InvariantPredicate();
NodeBitMap newLoopNodes = graph.createNodeBitMap();
for (BinaryArithmeticNode> binary : whole().nodes().filter(BinaryArithmeticNode.class)) {
- if (!binary.isAssociative()) {
+ if (!binary.mayReassociate()) {
continue;
}
ValueNode result = BinaryArithmeticNode.reassociateMatchedValues(binary, invariant, binary.getX(), binary.getY(), NodeView.DEFAULT);
diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java
index a1fc8c1541a50..34abba7e7d98a 100644
--- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java
+++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentInside.java
@@ -30,6 +30,7 @@
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.Equivalence;
+import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.debug.DebugCloseable;
import org.graalvm.compiler.debug.DebugContext;
@@ -230,7 +231,7 @@ public void insertWithinAfter(LoopEx loop, EconomicMap newFeatures = EnumSet.copyOf(features);
+ newFeatures.remove(DEAD_PHI_CYCLE_DETECTION);
+ return new CanonicalizerPhase(customSimplification, newFeatures);
+ }
+
public CanonicalizerPhase copyWithoutSimplification() {
EnumSet newFeatures = EnumSet.copyOf(features);
newFeatures.remove(CFG_SIMPLIFICATION);
@@ -314,7 +327,7 @@ public void usagesDroppedToZero(Node node) {
for (Node n : tool.workList) {
processNode(n, tool);
++sum;
- if (tool.allUsagesAvailable() && n.isAlive() && n instanceof PhiNode && ((PhiNode) n).isLoopPhi()) {
+ if (features.contains(DEAD_PHI_CYCLE_DETECTION) && tool.allUsagesAvailable() && n.isAlive() && n instanceof PhiNode && ((PhiNode) n).isLoopPhi()) {
if (phiPostProcessingWorkList == null) {
phiPostProcessingWorkList = EconomicSet.create();
}
diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ReassociationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ReassociationPhase.java
index c4945d4414857..a75f75d2405df 100644
--- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ReassociationPhase.java
+++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ReassociationPhase.java
@@ -48,12 +48,11 @@
import org.graalvm.compiler.nodes.util.GraphUtil;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
-
import jdk.vm.ci.meta.PrimitiveConstant;
/**
- * Rearrange {@link BinaryArithmeticNode#isAssociative() associative binary operations} for loop
- * invariants and constants.
+ * Rearrange binary arithmetic operations that {@linkplain BinaryArithmeticNode#mayReassociate() may
+ * be reassociated} for loop invariants and constants.
*/
public class ReassociationPhase extends BasePhase {
@@ -133,7 +132,7 @@ private static void reassociateConstants(StructuredGraph graph, CoreProviders co
try (DebugContext.Scope s = debug.scope("ReassociateConstants")) {
for (BinaryArithmeticNode> binary : graph.getNodes().filter(BinaryArithmeticNode.class)) {
// Skip re-associations to loop variant expressions.
- if (!binary.isAssociative() || (!loopNodes.isNew(binary) && loopNodes.contains(binary))) {
+ if (!binary.mayReassociate() || (!loopNodes.isNew(binary) && loopNodes.contains(binary))) {
continue;
}
ValueNode result = BinaryArithmeticNode.reassociateUnmatchedValues(binary, ValueNode.isConstantPredicate(), NodeView.DEFAULT);
diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py
index 7313199381a3a..5d178da70bc05 100644
--- a/espresso/mx.espresso/suite.py
+++ b/espresso/mx.espresso/suite.py
@@ -23,7 +23,7 @@
suite = {
"mxversion": "6.17.0",
"name": "espresso",
- "version" : "23.0.2.2",
+ "version" : "23.0.3.0",
"release" : False,
"groupId" : "org.graalvm.espresso",
"url" : "https://www.graalvm.org/reference-manual/java-on-truffle/",
diff --git a/regex/mx.regex/suite.py b/regex/mx.regex/suite.py
index 56acf56d92574..866191ba882de 100644
--- a/regex/mx.regex/suite.py
+++ b/regex/mx.regex/suite.py
@@ -43,7 +43,7 @@
"name" : "regex",
- "version" : "23.0.2.2",
+ "version" : "23.0.3.0",
"release" : False,
"groupId" : "org.graalvm.regex",
"url" : "http://www.graalvm.org/",
diff --git a/sdk/mx.sdk/mx_sdk_vm_impl.py b/sdk/mx.sdk/mx_sdk_vm_impl.py
index 763b45df424c4..0c55c26f27020 100644
--- a/sdk/mx.sdk/mx_sdk_vm_impl.py
+++ b/sdk/mx.sdk/mx_sdk_vm_impl.py
@@ -1166,7 +1166,7 @@ def generate_debug_info(self, image_config):
return self.is_debug_supported() and _generate_debuginfo(image_config)
def generate_separate_debug_info(self, image_config):
- return self.generate_debug_info(image_config) and self._separate_debuginfo_ext
+ return self.generate_debug_info(image_config) and not mx.get_opts().disable_debuginfo_stripping and self._separate_debuginfo_ext
def separate_debuginfo_ext(self):
return self._separate_debuginfo_ext
@@ -1174,6 +1174,8 @@ def separate_debuginfo_ext(self):
def get_debug_flags(self, image_config):
assert self.is_debug_supported()
flags = ['-g']
+ if not self.generate_separate_debug_info(image_config):
+ flags += ['-H:-StripDebugInfo']
if mx.is_darwin():
flags += ['-H:+UseOldDebugInfo']
if self.generate_separate_debug_info(image_config):
@@ -3787,6 +3789,7 @@ def graalvm_vendor_version():
mx.add_argument('--sources', action='store', help='Comma-separated list of projects and distributions of open-source components for which source file archives must be included' + (' (all by default).' if _debuginfo_default else '.'), default=None)
mx.add_argument('--debuginfo-dists', action='store_true', help='Generate debuginfo distributions.')
mx.add_argument('--generate-debuginfo', action='store', help='Comma-separated list of launchers and libraries (syntax: lib:polyglot) for which to generate debug information (`native-image -g`) (all by default)', default=None)
+mx.add_argument('--disable-debuginfo-stripping', action='store_true', help='Disable the stripping of debug symbols from the native image.')
mx.add_argument('--snapshot-catalog', action='store', help='Change the default URL of the component catalog for snapshots.', default=None)
mx.add_argument('--gds-snapshot-catalog', action='store', help='Change the default appended URL of the component catalog for snapshots.', default=None)
mx.add_argument('--release-catalog', action='store', help='Change the default URL of the component catalog for releases.', default=None)
diff --git a/sdk/mx.sdk/suite.py b/sdk/mx.sdk/suite.py
index b379e4c02fca1..831387f9a25b5 100644
--- a/sdk/mx.sdk/suite.py
+++ b/sdk/mx.sdk/suite.py
@@ -41,7 +41,7 @@
suite = {
"mxversion": "6.17.0",
"name" : "sdk",
- "version" : "23.0.2.2",
+ "version" : "23.0.3.0",
"release" : False,
"sourceinprojectwhitelist" : [],
"url" : "https://github.com/oracle/graal",
diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java
index 91a033dc1379e..7e18a44515213 100644
--- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java
+++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java
@@ -1239,6 +1239,11 @@ public ThreadScope createThreadScope() {
return null;
}
+ @Override
+ public boolean isInCurrentEngineHostCallback(Object engine) {
+ return false;
+ }
+
@Override
public OptionDescriptors createUnionOptionDescriptors(OptionDescriptors... optionDescriptors) {
return OptionDescriptors.createUnion(optionDescriptors);
diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java
index 463ed8b1f8cff..9a984a2c77e64 100644
--- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java
+++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/impl/AbstractPolyglotImpl.java
@@ -1186,6 +1186,10 @@ public ThreadScope createThreadScope() {
return getNext().createThreadScope();
}
+ public boolean isInCurrentEngineHostCallback(Object engine) {
+ return getNext().isInCurrentEngineHostCallback(engine);
+ }
+
public LogHandler newLogHandler(Object logHandlerOrStream) {
return getNext().newLogHandler(logHandlerOrStream);
}
diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py
index f4b8710cdc5c9..63744245d9bf2 100644
--- a/substratevm/mx.substratevm/suite.py
+++ b/substratevm/mx.substratevm/suite.py
@@ -2,7 +2,7 @@
suite = {
"mxversion": "6.17.0",
"name": "substratevm",
- "version" : "23.0.2.2",
+ "version" : "23.0.3.0",
"release" : False,
"url" : "https://github.com/oracle/graal/tree/master/substratevm",
diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java
index f2a23be29ba30..cb373d37299db 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java
@@ -40,6 +40,7 @@
import com.oracle.svm.core.heap.AbstractMXBean;
import com.oracle.svm.core.jdk.UninterruptibleUtils;
+import com.oracle.svm.core.util.UnsignedUtils;
import sun.management.Util;
@@ -72,11 +73,17 @@ UnsignedWord getInitialValue() {
abstract void afterCollection(GCAccounting accounting);
MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) {
- return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), getMaximumValue().rawValue());
+ return memoryUsage(usedAndCommitted, usedAndCommitted);
}
MemoryUsage memoryUsage(UnsignedWord used, UnsignedWord committed) {
- return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), getMaximumValue().rawValue());
+ /*
+ * Actual memory usage may temporarily exceed the maximum. It would be better to return
+ * UNDEFINED as the maximum value but this could break compatibility (i.e., we only do that
+ * starting with GraalVM 24.0).
+ */
+ long max = UnsignedUtils.max(getMaximumValue(), UnsignedUtils.max(used, committed)).rawValue();
+ return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), max);
}
@Override
diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java
index 4df6532b8e513..6db2eec7d7bc1 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java
@@ -279,7 +279,8 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) {
UnalignedHeapChunk.initialize(result, chunkSize);
assert objectSize.belowOrEqual(HeapChunk.availableObjectMemory(result)) : "UnalignedHeapChunk insufficient for requested object";
- if (HeapParameters.getZapProducedHeapChunks()) {
+ /* Avoid zapping if unaligned chunks are pre-zeroed. */
+ if (!CommittedMemoryProvider.get().areUnalignedChunksZeroed() && HeapParameters.getZapProducedHeapChunks()) {
zap(result, HeapParameters.getProducedHeapChunkZapWord());
}
diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapParameters.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapParameters.java
index 9c2be3f9a442b..42bb84bf63f63 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapParameters.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapParameters.java
@@ -123,6 +123,11 @@ static UnsignedWord getAlignedHeapChunkAlignment() {
return getAlignedHeapChunkSize();
}
+ @Fold
+ public static UnsignedWord getMinUnalignedChunkSize() {
+ return UnalignedHeapChunk.getChunkSizeForObject(HeapParameters.getLargeArrayThreshold());
+ }
+
@Fold
public static UnsignedWord getLargeArrayThreshold() {
long largeArrayThreshold = SerialAndEpsilonGCOptions.LargeArrayThreshold.getValue();
diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/UnalignedHeapChunk.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/UnalignedHeapChunk.java
index b6673242aec1a..92d350a0549ed 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/UnalignedHeapChunk.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/UnalignedHeapChunk.java
@@ -105,10 +105,6 @@ public static Pointer getObjectEnd(UnalignedHeader that) {
return HeapChunk.getEndPointer(that);
}
- public static UnsignedWord getOverhead() {
- return getObjectStartOffset();
- }
-
static UnsignedWord getChunkSizeForObject(UnsignedWord objectSize) {
UnsignedWord objectStart = getObjectStartOffset();
UnsignedWord alignment = WordFactory.unsigned(ConfigurationValues.getObjectLayout().getAlignment());
diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64LoadMethodPointerConstantOp.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64LoadMethodPointerConstantOp.java
index 46ec57d7ab269..df38fd162b75a 100644
--- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64LoadMethodPointerConstantOp.java
+++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64LoadMethodPointerConstantOp.java
@@ -28,6 +28,8 @@
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import com.oracle.svm.core.FrameAccess;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.StandardOp;
@@ -38,6 +40,7 @@
import jdk.vm.ci.code.Register;
import jdk.vm.ci.meta.AllocatableValue;
+import org.graalvm.nativeimage.Platform;
public final class AMD64LoadMethodPointerConstantOp extends AMD64LIRInstruction implements StandardOp.LoadConstantOp {
public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64LoadMethodPointerConstantOp.class);
@@ -53,8 +56,13 @@ public final class AMD64LoadMethodPointerConstantOp extends AMD64LIRInstruction
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
Register resultReg = asRegister(result);
- crb.recordInlineDataInCode(constant);
- masm.movq(resultReg, 0L, true);
+ if (!Platform.includedIn(Platform.DARWIN_AMD64.class)) {
+ crb.recordInlineDataInCode(constant);
+ masm.movq(resultReg, 0L, true);
+ } else {
+ /* [GR-43389] ld64 bug does not allow direct8 relocations in .text on darwin */
+ masm.movq(resultReg, (AMD64Address) crb.recordDataReferenceInCode(constant, FrameAccess.wordSize()));
+ }
}
@Override
diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java
index 353855263cbae..fc6e0012e97e6 100644
--- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java
+++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsSystemPropertiesSupport.java
@@ -356,7 +356,11 @@ public Pair getOsNameAndVersion() {
if (isWorkstation) {
switch (minorVersion) {
case 0:
- osName = "Windows 10";
+ if (buildNumber >= 22000) {
+ osName = "Windows 11";
+ } else {
+ osName = "Windows 10";
+ }
break;
default:
osName = "Windows NT (unknown)";
@@ -364,7 +368,9 @@ public Pair getOsNameAndVersion() {
} else {
switch (minorVersion) {
case 0:
- if (buildNumber > 17762) {
+ if (buildNumber > 20347) {
+ osName = "Windows Server 2022";
+ } else if (buildNumber > 17762) {
osName = "Windows Server 2019";
} else {
osName = "Windows Server 2016";
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java
index 263203da68669..6d2ecb783f730 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/Isolates.java
@@ -68,6 +68,7 @@ public class Isolates {
* they have a single native state that does not distinguish between isolates).
*/
public static boolean isCurrentFirst() {
+ VMError.guarantee(isCurrentFirst != null);
return isCurrentFirst;
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java
index 8abd5b7692ec6..a0840126a6df8 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java
@@ -868,23 +868,49 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
if (!success && DiagnosticLevel.unsafeOperationsAllowed(maxDiagnosticLevel)) {
/*
* If the stack pointer is not sufficiently aligned, then we might be in the middle
- * of a call (i.e., only the return address and the arguments are on the stack). In
- * that case, we can read the return address from the top of the stack, align the
- * stack pointer, and start a stack walk in the caller.
+ * of a call (i.e., only the arguments and the return address are on the stack).
*/
int expectedStackAlignment = ConfigurationValues.getTarget().stackAlignment;
if (sp.unsignedRemainder(expectedStackAlignment).notEqual(0) && sp.unsignedRemainder(ConfigurationValues.getTarget().wordSize).equal(0)) {
log.newline();
- log.string("WARNING: stack pointer is NOT aligned to ").signed(expectedStackAlignment).string(" bytes. Starting a stack walk in the most likely caller instead.").newline();
- ip = sp.readWord(0);
- sp = sp.add(ConfigurationValues.getTarget().wordSize);
-
- ThreadStackPrinter.printStacktrace(sp, ip, printVisitors[invocationCount - 1].reset(), log);
+ // Checkstyle: Allow raw info or warning printing - begin
+ log.string("Warning: stack pointer is not aligned to ").signed(expectedStackAlignment).string(" bytes.").newline();
+ // Checkstyle: Allow raw info or warning printing - end
}
+
+ startStackWalkInMostLikelyCaller(log, invocationCount, sp);
}
log.indent(false);
}
+
+ private static void startStackWalkInMostLikelyCaller(Log log, int invocationCount, Pointer originalSp) {
+ UnsignedWord stackBase = VMThreads.StackBase.get();
+ if (stackBase.equal(0)) {
+ /* We don't know the stack boundaries, so only search within 32 bytes. */
+ stackBase = originalSp.add(32);
+ }
+
+ /* Search until we find a valid return address. We may encounter false-positives. */
+ int wordSize = ConfigurationValues.getTarget().wordSize;
+ Pointer pos = originalSp;
+ while (pos.belowThan(stackBase)) {
+ CodePointer possibleIp = pos.readWord(0);
+ if (pointsIntoNativeImageCode(possibleIp)) {
+ Pointer sp = pos.add(wordSize);
+ log.newline();
+ log.string("Starting the stack walk in a possible caller:").newline();
+ ThreadStackPrinter.printStacktrace(sp, possibleIp, printVisitors[invocationCount - 1].reset(), log);
+ break;
+ }
+ pos = pos.add(wordSize);
+ }
+ }
+
+ @Uninterruptible(reason = "Prevent the GC from freeing the CodeInfo.")
+ private static boolean pointsIntoNativeImageCode(CodePointer possibleIp) {
+ return CodeInfoTable.lookupCodeInfo(possibleIp).isNonNull();
+ }
}
private static class DumpOtherStackTraces extends DiagnosticThunk {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
index b07164e6d7041..0bae9f604f8ac 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
@@ -452,6 +452,16 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o
@Option(help = "How many bytes to pad fields and classes marked @Contended with.") //
public static final HostedOptionKey ContendedPaddingWidth = new HostedOptionKey<>(128);
+ @Option(help = "Add additional header bytes to each object, for diagnostic purposes.", type = OptionType.Debug) //
+ public static final HostedOptionKey AdditionalHeaderBytes = new HostedOptionKey<>(0, SubstrateOptions::validateAdditionalHeaderBytes);
+
+ private static void validateAdditionalHeaderBytes(HostedOptionKey optionKey) {
+ int value = optionKey.getValue();
+ if (value < 0 || value % 4 != 0) {
+ throw UserError.abort("The option '%s' must be 0 or a multiple of 4.", optionKey.getName());
+ }
+ }
+
/*
* Isolate tear down options.
*/
@@ -921,4 +931,6 @@ public Boolean getValueOrDefault(UnmodifiableEconomicMap, Object> v
@Option(help = "file:doc-files/MissingRegistrationPathsHelp.txt")//
public static final HostedOptionKey ThrowMissingRegistrationErrorsPaths = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.build());
+ @Option(help = "Has no effect in this version of GraalVM. It is present for forward-compatibility with future versions of GraalVM.", type = OptionType.Expert, stability = OptionStability.EXPERIMENTAL) //
+ public static final HostedOptionKey UnlockExperimentalVMOptions = new HostedOptionKey<>(false);
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java
index 8ca7d3021dfa7..218a077363143 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java
@@ -59,6 +59,9 @@ private CEntryPointErrors() {
@Description("An argument was NULL.") //
public static final int NULL_ARGUMENT = 2;
+ @Description("Memory allocation failed, the OS is probably out of memory.") //
+ public static final int ALLOCATION_FAILED = 3;
+
@Description("The specified thread is not attached to the isolate.") //
public static final int UNATTACHED_THREAD = 4;
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/AbstractRuntimeCodeInstaller.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/AbstractRuntimeCodeInstaller.java
index f745ac0f495b2..b10ca00f9653a 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/AbstractRuntimeCodeInstaller.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/AbstractRuntimeCodeInstaller.java
@@ -47,11 +47,13 @@ protected Pointer allocateCodeMemory(long size) {
}
protected void makeCodeMemoryExecutableReadOnly(Pointer start, UnsignedWord size) {
- RuntimeCodeInfoAccess.makeCodeMemoryExecutableReadOnly((CodePointer) start, size);
+ int result = RuntimeCodeInfoAccess.makeCodeMemoryExecutableReadOnly((CodePointer) start, size);
+ VMError.guarantee(result == 0, "Failed to make code memory read only.");
}
protected void makeCodeMemoryExecutableWritable(Pointer start, UnsignedWord size) {
- RuntimeCodeInfoAccess.makeCodeMemoryExecutableWritable((CodePointer) start, size);
+ int result = RuntimeCodeInfoAccess.makeCodeMemoryExecutableWritable((CodePointer) start, size);
+ VMError.guarantee(result == 0, "Failed to make code memory writable.");
}
protected static void doInstallPrepared(SharedMethod method, CodeInfo codeInfo, SubstrateInstalledCode installedCode) {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
index febd8215da9be..61d9aca4aea4d 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
@@ -58,10 +58,11 @@ public final class ObjectLayout {
public ObjectLayout(SubstrateTargetDescription target, int referenceSize, int objectAlignment, int hubOffset,
int firstFieldOffset, int arrayLengthOffset, int arrayBaseOffset, int fixedIdentityHashOffset) {
- assert CodeUtil.isPowerOf2(referenceSize);
- assert CodeUtil.isPowerOf2(objectAlignment);
- assert hubOffset < firstFieldOffset && hubOffset < arrayLengthOffset;
- assert fixedIdentityHashOffset == -1 || (fixedIdentityHashOffset > 0 && fixedIdentityHashOffset < arrayLengthOffset);
+ assert CodeUtil.isPowerOf2(referenceSize) : referenceSize;
+ assert CodeUtil.isPowerOf2(objectAlignment) : objectAlignment;
+ assert arrayLengthOffset % Integer.BYTES == 0;
+ assert hubOffset < firstFieldOffset && hubOffset < arrayLengthOffset : hubOffset;
+ assert fixedIdentityHashOffset == -1 || (fixedIdentityHashOffset > 0 && fixedIdentityHashOffset < arrayLengthOffset) : fixedIdentityHashOffset;
this.target = target;
this.referenceSize = referenceSize;
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDataBuilder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDataBuilder.java
index 5db22aa8dab51..ac7c5bde7dbb5 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDataBuilder.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDataBuilder.java
@@ -28,9 +28,12 @@
import java.nio.ByteBuffer;
+import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
import org.graalvm.compiler.code.DataSection.Data;
import org.graalvm.compiler.code.DataSection.Patches;
import org.graalvm.compiler.lir.asm.DataBuilder;
+import org.graalvm.compiler.core.common.type.CompressibleConstant;
+import org.graalvm.compiler.core.common.type.TypedConstant;
import com.oracle.svm.core.FrameAccess;
import com.oracle.svm.core.SubstrateOptions;
@@ -48,9 +51,13 @@ public class SubstrateDataBuilder extends DataBuilder {
@Override
public Data createDataItem(Constant constant) {
int size;
- if (constant instanceof VMConstant) {
- assert constant instanceof SubstrateObjectConstant : "should be only VMConstant";
- return new ObjectData((SubstrateObjectConstant) constant);
+
+ if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
+ size = FrameAccess.wordSize();
+ return new ObjectData(size, size, methodPointerConstant);
+ } else if (constant instanceof VMConstant vmConstant) {
+ assert constant instanceof CompressibleConstant && constant instanceof TypedConstant : constant;
+ return new ObjectData(vmConstant);
} else if (JavaConstant.isNull(constant)) {
if (SubstrateObjectConstant.isCompressed((JavaConstant) constant)) {
size = ConfigurationValues.getObjectLayout().getReferenceSize();
@@ -58,16 +65,15 @@ public Data createDataItem(Constant constant) {
size = FrameAccess.uncompressedReferenceSize();
}
return createZeroData(size, size);
- } else if (constant instanceof SerializableConstant) {
- SerializableConstant s = (SerializableConstant) constant;
- return createSerializableData(s);
+ } else if (constant instanceof SerializableConstant serializableConstant) {
+ return createSerializableData(serializableConstant);
} else {
throw new JVMCIError(String.valueOf(constant));
}
}
public static class ObjectData extends Data {
- private final SubstrateObjectConstant constant;
+ private final VMConstant constant;
protected ObjectData(SubstrateObjectConstant constant) {
super(ConfigurationValues.getObjectLayout().getReferenceSize(), ConfigurationValues.getObjectLayout().getReferenceSize());
@@ -75,7 +81,18 @@ protected ObjectData(SubstrateObjectConstant constant) {
this.constant = constant;
}
- public SubstrateObjectConstant getConstant() {
+ protected ObjectData(int alignment, int size, VMConstant constant) {
+ super(alignment, size);
+ this.constant = constant;
+ }
+
+ protected ObjectData(VMConstant constant) {
+ this(ConfigurationValues.getObjectLayout().getReferenceSize(), ConfigurationValues.getObjectLayout().getReferenceSize(), constant);
+ assert ((CompressibleConstant) constant).isCompressed() == ReferenceAccess.singleton()
+ .haveCompressedReferences() : "Constant object references in compiled code must be compressed (base-relative)";
+ }
+
+ public VMConstant getConstant() {
return constant;
}
@@ -85,7 +102,7 @@ protected void emit(ByteBuffer buffer, Patches patches) {
if (getSize() == Integer.BYTES) {
buffer.putInt(0);
} else if (getSize() == Long.BYTES) {
- buffer.putLong(0L);
+ buffer.putLong(0);
} else {
shouldNotReachHere("Unsupported object constant reference size: " + getSize());
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java
index 4101185e60077..af7327cec9f5d 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java
@@ -88,6 +88,7 @@
import com.oracle.svm.core.graal.nodes.CEntryPointEnterNode;
import com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode;
import com.oracle.svm.core.graal.nodes.CEntryPointUtilityNode;
+import com.oracle.svm.core.graal.nodes.WriteCurrentVMThreadNode;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.core.heap.PhysicalMemory;
import com.oracle.svm.core.heap.ReferenceHandler;
@@ -200,8 +201,7 @@ public static int createIsolateSnippet(CEntryPointCreateIsolateParameters parame
Safepoint.transitionNativeToJava(false);
}
- result = runtimeCallInitializeIsolate(INITIALIZE_ISOLATE, parameters);
- return result;
+ return runtimeCallInitializeIsolate(INITIALIZE_ISOLATE, parameters);
}
@Uninterruptible(reason = "Thread state not yet set up.")
@@ -276,15 +276,40 @@ public static boolean isIsolateInitialized() {
return isolateInitialized;
}
+ @Uninterruptible(reason = "Must be uninterruptible because thread state is not set up after leaveTearDownIsolate().")
@SubstrateForeignCallTarget(stubCallingConvention = false)
private static int initializeIsolate(CEntryPointCreateIsolateParameters parameters) {
- boolean firstIsolate = false;
+ int result = initializeIsolateInterruptibly(parameters);
+ if (result != CEntryPointErrors.NO_ERROR) {
+ CEntryPointActions.leaveTearDownIsolate();
+ /* Extra return is needed because of validation. */
+ return result;
+ }
+ return result;
+ }
+
+ @Uninterruptible(reason = "Used as a transition between uninterruptible and interruptible code", calleeMustBe = false)
+ private static int initializeIsolateInterruptibly(CEntryPointCreateIsolateParameters parameters) {
+ return initializeIsolateInterruptibly0(parameters);
+ }
- final long initStateAddr = FIRST_ISOLATE_INIT_STATE.get().rawValue();
- int state = Unsafe.getUnsafe().getInt(initStateAddr);
- if (state != FirstIsolateInitStates.SUCCESSFUL) {
- firstIsolate = Unsafe.getUnsafe().compareAndSetInt(null, initStateAddr, FirstIsolateInitStates.UNINITIALIZED, FirstIsolateInitStates.IN_PROGRESS);
- if (!firstIsolate) {
+ private static int initializeIsolateInterruptibly0(CEntryPointCreateIsolateParameters parameters) {
+ /*
+ * The VM operation thread must be started early as no VM operations can be scheduled before
+ * this thread is fully started. The isolate teardown may also use VM operations.
+ */
+ if (VMOperationControl.useDedicatedVMOperationThread()) {
+ VMOperationControl.startVMOperationThread();
+ }
+
+ long initStateAddr = FIRST_ISOLATE_INIT_STATE.get().rawValue();
+ boolean firstIsolate = Unsafe.getUnsafe().compareAndSetInt(null, initStateAddr, FirstIsolateInitStates.UNINITIALIZED, FirstIsolateInitStates.IN_PROGRESS);
+
+ Isolates.setCurrentIsFirstIsolate(firstIsolate);
+
+ if (!firstIsolate) {
+ int state = Unsafe.getUnsafe().getInt(initStateAddr);
+ if (state != FirstIsolateInitStates.SUCCESSFUL) {
while (state == FirstIsolateInitStates.IN_PROGRESS) { // spin-wait for first isolate
PauseNode.pause();
state = Unsafe.getUnsafe().getIntVolatile(null, initStateAddr);
@@ -294,16 +319,6 @@ private static int initializeIsolate(CEntryPointCreateIsolateParameters paramete
}
}
}
- Isolates.setCurrentIsFirstIsolate(firstIsolate);
-
- /*
- * The VM operation thread must be started early as no VM operations can be scheduled before
- * this thread is fully started.
- */
- if (VMOperationControl.useDedicatedVMOperationThread()) {
- VMOperationControl.startVMOperationThread();
- }
-
/*
* The reference handler thread must also be started early. Otherwise, it could happen that
* the GC publishes pending references but there is no thread to process them. This could
@@ -334,7 +349,6 @@ private static int initializeIsolate(CEntryPointCreateIsolateParameters paramete
Log.logStream().println("error: " + e.getMessage());
System.exit(1);
} else {
- CEntryPointActions.leaveTearDownIsolate();
return CEntryPointErrors.ARGUMENT_PARSING_FAILED;
}
}
@@ -346,12 +360,11 @@ private static int initializeIsolate(CEntryPointCreateIsolateParameters paramete
boolean success = PlatformNativeLibrarySupport.singleton().initializeBuiltinLibraries();
if (firstIsolate) { // let other isolates (if any) initialize now
- state = success ? FirstIsolateInitStates.SUCCESSFUL : FirstIsolateInitStates.FAILED;
+ int state = success ? FirstIsolateInitStates.SUCCESSFUL : FirstIsolateInitStates.FAILED;
Unsafe.getUnsafe().putIntVolatile(null, initStateAddr, state);
}
if (!success) {
- CEntryPointActions.leaveTearDownIsolate();
return CEntryPointErrors.ISOLATE_INITIALIZATION_FAILED;
}
@@ -369,7 +382,6 @@ private static int initializeIsolate(CEntryPointCreateIsolateParameters paramete
} catch (Throwable t) {
System.err.println("Uncaught exception while running initialization hooks:");
t.printStackTrace();
- CEntryPointActions.leaveTearDownIsolate();
return CEntryPointErrors.ISOLATE_INITIALIZATION_FAILED;
}
@@ -506,6 +518,7 @@ private static int tearDownIsolate() {
int result = Isolates.tearDownCurrent();
// release the heap memory associated with final isolate thread
VMThreads.singleton().freeIsolateThread(finalThread);
+ WriteCurrentVMThreadNode.writeCurrentVMThread(WordFactory.nullPointer());
return result;
} catch (Throwable t) {
return reportException(t);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java
index 5b4542c341c9a..a537bb00f185a 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrEvent.java
@@ -28,6 +28,7 @@
import org.graalvm.nativeimage.Platforms;
import com.oracle.svm.core.Uninterruptible;
+import com.oracle.svm.core.thread.JavaThreads;
/**
* This file contains the VM-level events that Native Image supports on all JDK versions. The event
@@ -89,18 +90,11 @@ public String getName() {
@Uninterruptible(reason = "Prevent races with VM operations that start/stop recording.", callerMustBe = true)
public boolean shouldEmit() {
- assert !hasDuration;
- return shouldEmit0();
- }
-
- @Uninterruptible(reason = "Prevent races with VM operations that start/stop recording.", callerMustBe = true)
- public boolean shouldEmit(long durationTicks) {
- assert hasDuration;
- return shouldEmit0() && durationTicks >= SubstrateJVM.get().getThresholdTicks(this);
+ return shouldEmit0() && !JfrThreadLocal.isThreadExcluded(JavaThreads.getCurrentThreadOrNull());
}
@Uninterruptible(reason = "Prevent races with VM operations that start/stop recording.", callerMustBe = true)
private boolean shouldEmit0() {
- return SubstrateJVM.get().isRecording() && SubstrateJVM.get().isEnabled(this) && !SubstrateJVM.get().isCurrentThreadExcluded();
+ return SubstrateJVM.get().isRecording() && SubstrateJVM.get().isEnabled(this);
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java
index ba310d083ca48..bada6464c6f9b 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrThreadLocal.java
@@ -222,8 +222,8 @@ private static void flushToGlobalMemoryAndRetireBuffer(JfrBuffer buffer) {
* This method excludes/includes a thread from JFR (emitting events and sampling). At the
* moment, only the current thread may be excluded/included. See GR-44616.
*/
- public void setExcluded(Thread thread, boolean excluded) {
- if (thread == null || !thread.equals(Thread.currentThread())) {
+ public static void setExcluded(Thread thread, boolean excluded) {
+ if (thread == null || thread != JavaThreads.getCurrentThreadOrNull()) {
return;
}
IsolateThread currentIsolateThread = CurrentIsolate.getCurrentThread();
@@ -241,18 +241,18 @@ public void setExcluded(Thread thread, boolean excluded) {
* See {@link PlatformThreads#ensureCurrentAssigned(String, ThreadGroup, boolean)} where a
* {@link Thread} object must be created before it can be assigned to the current thread. This
* may happen during shutdown in {@link JavaMainWrapper}. Therefore, this method must account
- * for the case where {@link Thread#currentThread()} returns null.
+ * for the case where {@link JavaThreads#getCurrentThreadOrNull()} returns null.
*/
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
- public boolean isCurrentThreadExcluded() {
- if (Thread.currentThread() == null) {
+ public static boolean isThreadExcluded(Thread thread) {
+ if (thread == null) {
return true;
}
- Target_java_lang_Thread tjlt = SubstrateUtil.cast(Thread.currentThread(), Target_java_lang_Thread.class);
+ Target_java_lang_Thread tjlt = SubstrateUtil.cast(thread, Target_java_lang_Thread.class);
return tjlt.jfrExcluded;
}
- public Target_jdk_jfr_internal_EventWriter getEventWriter() {
+ public static Target_jdk_jfr_internal_EventWriter getEventWriter() {
return javaEventWriter.get();
}
@@ -269,7 +269,7 @@ public Target_jdk_jfr_internal_EventWriter newEventWriter() {
throw new OutOfMemoryError("OOME for thread local buffer");
}
- Target_jdk_jfr_internal_EventWriter result = JfrEventWriterAccess.newEventWriter(buffer, isCurrentThreadExcluded());
+ Target_jdk_jfr_internal_EventWriter result = JfrEventWriterAccess.newEventWriter(buffer, isThreadExcluded(JavaThreads.getCurrentThreadOrNull()));
javaEventWriter.set(result);
return result;
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java
index d6051542891c0..375e82d5a6f1f 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java
@@ -611,7 +611,7 @@ public void subscribeLogLevel(@SuppressWarnings("unused") LogTag lt, @SuppressWa
* See {@link JVM#getEventWriter}.
*/
public Target_jdk_jfr_internal_EventWriter getEventWriter() {
- return threadLocal.getEventWriter();
+ return JfrThreadLocal.getEventWriter();
}
/**
@@ -680,26 +680,6 @@ public Object getConfiguration(Class extends Event> eventClass) {
return DynamicHub.fromClass(eventClass).getJfrEventConfiguration();
}
- public void setExcluded(Thread thread, boolean excluded) {
- getThreadLocal().setExcluded(thread, excluded);
- }
-
- public boolean isExcluded(Thread thread) {
- /*
- * Only the current thread is passed to this method in JDK 17, 19, and 20. Eventually, we
- * will need to implement that in a more general way though, see GR-44616.
- */
- if (!thread.equals(Thread.currentThread())) {
- return false;
- }
- return isCurrentThreadExcluded();
- }
-
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
- public boolean isCurrentThreadExcluded() {
- return getThreadLocal().isCurrentThreadExcluded();
- }
-
private static class JfrBeginRecordingOperation extends JavaVMOperation {
JfrBeginRecordingOperation() {
super(VMOperationInfos.get(JfrBeginRecordingOperation.class, "JFR begin recording", SystemEffect.SAFEPOINT));
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java
index c788d5cf93b89..76a40fea28bc1 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java
@@ -456,19 +456,19 @@ public boolean shouldRotateDisk() {
@Substitute
@TargetElement(onlyWith = JDK17OrLater.class) //
public void include(Thread thread) {
- SubstrateJVM.get().setExcluded(thread, false);
+ JfrThreadLocal.setExcluded(thread, false);
}
@Substitute
@TargetElement(onlyWith = JDK17OrLater.class) //
public void exclude(Thread thread) {
- SubstrateJVM.get().setExcluded(thread, true);
+ JfrThreadLocal.setExcluded(thread, true);
}
@Substitute
@TargetElement(onlyWith = JDK17OrLater.class) //
public boolean isExcluded(Thread thread) {
- return SubstrateJVM.get().isExcluded(thread);
+ return JfrThreadLocal.isThreadExcluded(thread);
}
@Substitute
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java
index f381b6ed1b4d1..4888517486e26 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractCommittedMemoryProvider.java
@@ -42,6 +42,7 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.c.function.CEntryPointErrors;
import com.oracle.svm.core.code.RuntimeCodeCache;
+import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.heap.Heap;
import com.oracle.svm.core.util.UnsignedUtils;
import com.oracle.svm.core.util.VMError;
@@ -109,7 +110,7 @@ public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment)
@Override
public Pointer allocateUnalignedChunk(UnsignedWord nbytes) {
- return allocate(nbytes, WordFactory.unsigned(1), false);
+ return allocate(nbytes, getAlignmentForUnalignedChunks(), false);
}
@Override
@@ -172,6 +173,16 @@ private void free(PointerBase start, UnsignedWord nbytes) {
}
}
+ /**
+ * Unaligned chunks also need some minimal alignment - otherwise, the data in the chunk header
+ * or the Java heap object within the unaligned chunk would be misaligned.
+ */
+ @Fold
+ protected static UnsignedWord getAlignmentForUnalignedChunks() {
+ int alignment = Math.max(ConfigurationValues.getTarget().wordSize, ConfigurationValues.getObjectLayout().getAlignment());
+ return WordFactory.unsigned(alignment);
+ }
+
private final VirtualMemoryTracker tracker = new VirtualMemoryTracker();
public static class VirtualMemoryTracker {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java
index d54b95287d574..273ad6e10cb47 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/CommittedMemoryProvider.java
@@ -32,7 +32,6 @@
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;
import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordFactory;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.c.function.CEntryPointCreateIsolateParameters;
@@ -43,12 +42,6 @@
* memory or swap space.
*/
public interface CommittedMemoryProvider {
- /**
- * Value for alignment parameters that indicates that no specific alignment is required (other
- * than the {@linkplain #getGranularity() granularity} usually).
- */
- UnsignedWord UNALIGNED = WordFactory.unsigned(1);
-
@Fold
static CommittedMemoryProvider get() {
return ImageSingletons.lookup(CommittedMemoryProvider.class);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
index 82aa1ac06088d..53dacdd1b157d 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java
@@ -458,6 +458,17 @@ public static long getCurrentThreadIdOrZero() {
}
return 0L;
}
+
+ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ public static Thread getCurrentThreadOrNull() {
+ Thread thread = PlatformThreads.currentThread.get();
+ if (thread == null) {
+ return null;
+ }
+
+ Target_java_lang_Thread tjlt = SubstrateUtil.cast(thread, Target_java_lang_Thread.class);
+ return (tjlt.vthread != null) ? tjlt.vthread : thread;
+ }
}
/* GR-43733: this class can be removed when we drop the JDK 17 support. */
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java
index d22e987f66af8..fd91ae3cfa1f9 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java
@@ -1029,6 +1029,7 @@ static boolean compareAndSetThreadStatus(Thread thread, int expectedStatus, int
}
}
+ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
static boolean isAlive(Thread thread) {
int threadStatus = getThreadStatus(thread);
return !(threadStatus == ThreadStatus.NEW || threadStatus == ThreadStatus.TERMINATED);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
index cce5b52685ebf..189253efe91a9 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java
@@ -320,9 +320,13 @@ static Thread currentCarrierThread() {
@Substitute
@TargetElement(name = "currentThread", onlyWith = ContinuationsSupported.class)
static Thread currentVThread() {
- Thread thread = PlatformThreads.currentThread.get();
- Target_java_lang_Thread tjlt = SubstrateUtil.cast(thread, Target_java_lang_Thread.class);
- return (tjlt.vthread != null) ? tjlt.vthread : thread;
+ Thread thread = JavaThreads.getCurrentThreadOrNull();
+ if (GraalDirectives.inIntrinsic()) {
+ ReplacementsUtil.dynamicAssert(thread != null, "Thread has not been set yet");
+ } else {
+ assert thread != null : "Thread has not been set yet";
+ }
+ return thread;
}
@SuppressWarnings("static-method")
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMOperationControl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMOperationControl.java
index d857bcbb8e474..a17aa4afaac49 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMOperationControl.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMOperationControl.java
@@ -435,7 +435,7 @@ public IsolateThread getIsolateThread() {
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public boolean isRunning() {
- return isolateThread.isNonNull() && !stopped;
+ return PlatformThreads.isAlive(thread);
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/PointerUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/PointerUtils.java
index 6eaa28430b1d4..306d3b796109f 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/PointerUtils.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/PointerUtils.java
@@ -101,6 +101,7 @@ public static UnsignedWord absoluteDifference(PointerBase pointer1, PointerBase
* @param y Another Pointer.
* @return The whichever Pointer is smaller.
*/
+ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static T min(T x, T y) {
return (((Pointer) x).belowOrEqual((Pointer) y)) ? x : y;
}
@@ -112,6 +113,7 @@ public static T min(T x, T y) {
* @param y Another Pointer.
* @return The whichever Pointer is larger.
*/
+ @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static T max(T x, T y) {
return (((Pointer) x).aboveOrEqual((Pointer) y)) ? x : y;
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/VMError.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/VMError.java
index bbee4ee3dae2b..10335e80140bd 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/VMError.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/VMError.java
@@ -64,6 +64,9 @@ public static final class HostedError extends Error {
}
+ public static final String msgShouldNotReachHere = "should not reach here";
+ public static final String msgShouldNotReachHereAtRuntime = msgShouldNotReachHere + ": this code is expected to be unreachable at runtime";
+
public static RuntimeException shouldNotReachHere() {
throw new HostedError("should not reach here");
}
@@ -80,6 +83,13 @@ public static RuntimeException shouldNotReachHere(String msg, Throwable cause) {
throw new HostedError(msg, cause);
}
+ /**
+ * A hardcoded list of options (if, switch) did not handle the case actually provided.
+ */
+ public static RuntimeException shouldNotReachHereAtRuntime() {
+ throw new HostedError(msgShouldNotReachHereAtRuntime);
+ }
+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static void guarantee(boolean condition) {
if (!condition) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java
index 38c9362fc31c9..ab8704e5b8ebd 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java
@@ -140,13 +140,13 @@ public static ObjectLayout createObjectLayout() {
public static ObjectLayout createObjectLayout(JavaKind referenceKind, boolean disableOptionalIdentityHash) {
SubstrateTargetDescription target = ConfigurationValues.getTarget();
int referenceSize = target.arch.getPlatformKind(referenceKind).getSizeInBytes();
- int headerSize = referenceSize;
int intSize = target.arch.getPlatformKind(JavaKind.Int).getSizeInBytes();
int objectAlignment = 8;
- int headerOffset = 0;
+ int hubOffset = 0;
+ int headerSize = hubOffset + referenceSize;
+
int identityHashCodeOffset;
- int firstFieldOffset;
if (!disableOptionalIdentityHash && SubstrateOptions.SpawnIsolates.getValue() && headerSize + referenceSize <= objectAlignment) {
/*
* References are relative to the heap base, so we should be able to use fewer bits in
@@ -158,15 +158,18 @@ public static ObjectLayout createObjectLayout(JavaKind referenceKind, boolean di
* individual object was assigned an identity hash code after allocation.
*/
identityHashCodeOffset = -1;
- firstFieldOffset = headerOffset + headerSize;
} else { // need all object header bits except for lowest-order bits freed up by alignment
- identityHashCodeOffset = headerOffset + referenceSize;
- firstFieldOffset = identityHashCodeOffset + intSize;
+ identityHashCodeOffset = headerSize;
+ headerSize += intSize;
}
- int arrayLengthOffset = firstFieldOffset;
+
+ headerSize += SubstrateOptions.AdditionalHeaderBytes.getValue();
+
+ int firstFieldOffset = headerSize;
+ int arrayLengthOffset = headerSize;
int arrayBaseOffset = arrayLengthOffset + intSize;
- return new ObjectLayout(target, referenceSize, objectAlignment, headerOffset, firstFieldOffset, arrayLengthOffset, arrayBaseOffset, identityHashCodeOffset);
+ return new ObjectLayout(target, referenceSize, objectAlignment, hubOffset, firstFieldOffset, arrayLengthOffset, arrayBaseOffset, identityHashCodeOffset);
}
public SVMHost createHostVM(OptionValues options, ClassLoader classLoader, ClassInitializationSupport classInitializationSupport,
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityHandlerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityHandlerFeature.java
index 21a5ee6371918..e32b859e0c190 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityHandlerFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityHandlerFeature.java
@@ -32,6 +32,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -44,6 +45,7 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
+import com.oracle.svm.core.util.ConcurrentIdentityHashMap;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
@@ -52,8 +54,8 @@
@AutomaticallyRegisteredFeature
public class ReachabilityHandlerFeature extends ReachabilityHandler implements InternalFeature {
- private final IdentityHashMap