@Test public void testBlockSchedule() { ScheduleResult schedule = getFinalSchedule("testBlockScheduleSnippet", TestMode.WITHOUT_FRAMESTATES); StructuredGraph graph = schedule.getCFG().graph; NodeIterable<WriteNode> writeNodes = graph.getNodes().filter(WriteNode.class); assertDeepEquals(1, schedule.getCFG().getBlocks().size()); assertDeepEquals(8, writeNodes.count()); assertDeepEquals(1, graph.getNodes().filter(FloatingReadNode.class).count()); FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first(); WriteNode[] writes = new WriteNode[8]; int i = 0; for (WriteNode n : writeNodes) { writes[i] = n; i++; } assertOrderedAfterSchedule(schedule, writes[4], read); assertOrderedAfterSchedule(schedule, read, writes[5]); for (int j = 0; j < 7; j++) { assertOrderedAfterSchedule(schedule, writes[j], writes[j + 1]); } }
@Test public void testLoop9() { ScheduleResult schedule = getFinalSchedule("testLoop9Snippet", TestMode.WITHOUT_FRAMESTATES); StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); 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()); Assert.assertEquals(0, readBlock.getLoopDepth()); }
@Test public void testArrayCopy() { ScheduleResult schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); assertTrue( ret.result() + " should be a FloatingReadNode", ret.result() instanceof FloatingReadNode); assertDeepEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); assertReadWithinAllReturnBlocks(schedule, true); }
private StructuredGraph parseAndProcess(String snippet) { StructuredGraph graph = parse(snippet); LocalNode local = graph.getNodes(LocalNode.class).first(); ConstantNode constant = ConstantNode.forInt(0, graph); for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { n.replaceFirstInput(local, constant); } Map<Invoke, Double> hints = new HashMap<>(); for (Invoke invoke : graph.getInvokes()) { hints.put(invoke, 1000d); } Assumptions assumptions = new Assumptions(false); new InliningPhase( runtime(), hints, replacements, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL) .apply(graph); new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; }
@Test public void test2() { StructuredGraph graph = parseAndProcess("test2Snippet"); NodeIterable<MonitorExitNode> monitors = graph.getNodes(MonitorExitNode.class); Assert.assertEquals(1, monitors.count()); Assert.assertEquals(monitors.first().stateAfter().bci, 3); }
@Override protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); if (ccn != null) { CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false)); graph.replaceFixedWithFixed(ccn, ccnNew); } }
private void assertReadWithinAllReturnBlocks(ScheduleResult schedule, boolean withinReturnBlock) { StructuredGraph graph = schedule.getCFG().graph; assertTrue(graph.getNodes(ReturnNode.TYPE).isNotEmpty()); int withRead = 0; int returnBlocks = 0; for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) { Block block = schedule.getCFG().getNodeToBlock().get(returnNode); for (Node node : schedule.getBlockToNodesMap().get(block)) { if (node instanceof FloatingReadNode) { withRead++; break; } } returnBlocks++; } assertDeepEquals(withRead == returnBlocks, withinReturnBlock); }
@Override protected void run(final StructuredGraph graph, PhaseContext context) { assert graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies"; if (graph.getNodes(DeoptimizeNode.TYPE).isEmpty()) { return; } for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.TYPE)) { assert d.isAlive(); visitDeoptBegin( AbstractBeginNode.prevBegin(d), d.action(), d.reason(), d.getSpeculation(), graph); } if (context != null) { for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.TYPE)) { trySplitFixedGuard(fixedGuard, context); } } new DeadCodeEliminationPhase(Optional).apply(graph); }
@Test public void testSimple() { for (TestMode mode : TestMode.values()) { ScheduleResult schedule = getFinalSchedule("testSimpleSnippet", mode); StructuredGraph graph = schedule.getCFG().graph; assertReadAndWriteInSameBlock(schedule, true); assertOrderedAfterSchedule( schedule, graph.getNodes().filter(FloatingReadNode.class).first(), graph.getNodes().filter(WriteNode.class).first()); } }
@Override protected boolean checkLowTierGraph(StructuredGraph graph) { for (ConstantNode constantNode : graph.getNodes().filter(ConstantNode.class)) { assert constantNode.asJavaConstant() == null || constantNode.asJavaConstant().getJavaKind() != JavaKind.Object || constantNode.asJavaConstant().isDefaultForKind() : "Found unexpected object constant " + constantNode + ", this should have been removed by the LoadJavaMirrorWithKlassPhase."; } return true; }
@Override protected boolean checkMidTierGraph(StructuredGraph graph) { int count = 0; for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { ValueNode value = isNull.getValue(); if (value instanceof CompressionNode) { count++; isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); } } Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); return super.checkMidTierGraph(graph); }
@Test public void testValueProxyInputs() { StructuredGraph graph = parseEager("testValueProxyInputsSnippet", AllowAssumptions.YES); for (FrameState fs : graph.getNodes().filter(FrameState.class).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); } SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); NodeMap<Block> nodeToBlock = schedule.getCFG().getNodeToBlock(); assertTrue(graph.getNodes().filter(LoopExitNode.class).count() == 1); LoopExitNode loopExit = graph.getNodes().filter(LoopExitNode.class).first(); List<Node> list = schedule.nodesFor(nodeToBlock.get(loopExit)); for (BinaryArithmeticNode<?> node : graph.getNodes().filter(BinaryArithmeticNode.class)) { if (!(node instanceof AddNode)) { assertTrue(node.toString(), nodeToBlock.get(node) == nodeToBlock.get(loopExit)); assertTrue( list.indexOf(node) + " < " + list.indexOf(loopExit) + ", " + node + ", " + loopExit, list.indexOf(node) < list.indexOf(loopExit)); } } }
@SuppressWarnings("try") private ScheduleResult getFinalSchedule( final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); try (Scope d = Debug.scope("FloatingReadTest", graph)) { try (OverrideScope s = OptionValue.override( OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { HighTierContext context = getDefaultHighTierContext(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); canonicalizer.apply(graph, context); if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { new InliningPhase(canonicalizer).apply(graph, context); } new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER) .apply(graph, context); if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { graph.clearAllStateAfter(); } Debug.dump(graph, "after removal of framestates"); new FloatingReadPhase().apply(graph); new RemoveValueProxyPhase().apply(graph); MidTierContext midContext = new MidTierContext( getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER) .apply(graph, midContext); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER) .apply(graph, midContext); SchedulePhase schedule = new SchedulePhase(schedulingStrategy); schedule.apply(graph); assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); return graph.getLastSchedule(); } } catch (Throwable e) { throw Debug.handle(e); } }
private static void deleteNodes(NodeFlood flood, StructuredGraph graph) { BiConsumer<Node, Node> consumer = (n, input) -> { if (input.isAlive() && flood.isMarked(input)) { input.removeUsage(n); } }; for (Node node : graph.getNodes()) { if (!flood.isMarked(node)) { node.markDeleted(); node.acceptInputs(consumer); metricNodesRemoved.increment(); } } }
private void testMethod(Method method, Object receiver, Object... args) { try { // Invoke the method to ensure it has a type profile for (int i = 0; i < 5000; i++) { method.invoke(receiver, args); } } catch (Exception e) { throw new RuntimeException(e); } ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); StructuredGraph g = parseProfiled(javaMethod, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new InlineMethodSubstitutionsPolicy(), new CanonicalizerPhase()) .apply(g, context); new CanonicalizerPhase().apply(g, context); Assert.assertTrue(g.getNodes().filter(CheckCastNode.class).isEmpty()); }
private static Stream<Class<?>> nodeClassStream(StructuredGraph graph) { return StreamSupport.stream(graph.getNodes().spliterator(), false).map(node -> node.getClass()); }
private static void assertReadAndWriteInSameBlock(ScheduleResult schedule, boolean inSame) { StructuredGraph graph = schedule.getCFG().graph; FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first(); WriteNode write = graph.getNodes().filter(WriteNode.class).first(); assertTrue(!(inSame ^ schedule.getCFG().blockFor(read) == schedule.getCFG().blockFor(write))); }
private void scheduleEarliestIterative( BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph) { BitSet floatingReads = new BitSet(cfg.getBlocks().length); // Add begin nodes as the first entry and set the block for phi nodes. for (Block b : cfg.getBlocks()) { AbstractBeginNode beginNode = b.getBeginNode(); ArrayList<Node> nodes = new ArrayList<>(); nodeToBlock.set(beginNode, b); nodes.add(beginNode); blockToNodes.put(b, nodes); if (beginNode instanceof AbstractMergeNode) { AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode; for (PhiNode phi : mergeNode.phis()) { nodeToBlock.set(phi, b); } } else if (beginNode instanceof LoopExitNode) { LoopExitNode loopExitNode = (LoopExitNode) beginNode; for (ProxyNode proxy : loopExitNode.proxies()) { nodeToBlock.set(proxy, b); } } } NodeStack stack = new NodeStack(); // Start analysis with control flow ends. Block[] reversePostOrder = cfg.reversePostOrder(); for (int j = reversePostOrder.length - 1; j >= 0; --j) { Block b = reversePostOrder[j]; FixedNode endNode = b.getEndNode(); if (isFixedEnd(endNode)) { stack.push(endNode); nodeToBlock.set(endNode, b); } } processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack); // Visit back input edges of loop phis. boolean changed; boolean unmarkedPhi; do { changed = false; unmarkedPhi = false; for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) { for (PhiNode phi : loopBegin.phis()) { if (visited.isMarked(phi)) { for (int i = 0; i < loopBegin.getLoopEndCount(); ++i) { Node node = phi.valueAt(i + loopBegin.forwardEndCount()); if (node != null && !visited.isMarked(node)) { changed = true; stack.push(node); processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack); } } } else { unmarkedPhi = true; } } } /* * the processing of one loop phi could have marked a previously checked loop phi, * therefore this needs to be iterative. */ } while (unmarkedPhi && changed); // Check for dead nodes. if (!immutableGraph && visited.getCounter() < graph.getNodeCount()) { for (Node n : graph.getNodes()) { if (!visited.isMarked(n)) { n.clearInputs(); n.markDeleted(); } } } // Add end nodes as the last nodes in each block. for (Block b : cfg.getBlocks()) { FixedNode endNode = b.getEndNode(); if (isFixedEnd(endNode)) { if (endNode != b.getBeginNode()) { addNode(blockToNodes, b, endNode); } } } if (!floatingReads.isEmpty()) { for (Block b : cfg.getBlocks()) { if (floatingReads.get(b.getId())) { resortEarliestWithinBlock(b, blockToNodes, nodeToBlock, visited); } } } assert MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes); }