6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.test; 24 25 import java.util.List; 26 import org.junit.Assert; 27 import org.junit.Test; 28 import org.graalvm.compiler.debug.Debug; 29 import org.graalvm.compiler.debug.Debug.Scope; 30 import org.graalvm.compiler.debug.DebugConfig; 31 import org.graalvm.compiler.debug.DebugConfigScope; 32 import org.graalvm.compiler.debug.DebugDumpScope; 33 import org.graalvm.compiler.debug.internal.DebugScope; 34 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 35 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; 36 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; 37 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; 38 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; 39 import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; 40 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; 41 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 42 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; 43 import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopyNode; 44 import org.graalvm.compiler.nodes.AbstractBeginNode; 45 import org.graalvm.compiler.nodes.AbstractMergeNode; 46 import org.graalvm.compiler.nodes.FieldLocationIdentity; 47 import org.graalvm.compiler.nodes.FixedNode; 48 import org.graalvm.compiler.nodes.FixedWithNextNode; 49 import org.graalvm.compiler.nodes.LoopBeginNode; 50 import org.graalvm.compiler.nodes.LoopExitNode; 51 import org.graalvm.compiler.nodes.StructuredGraph; 52 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 53 import org.graalvm.compiler.nodes.memory.WriteNode; 54 import org.graalvm.compiler.nodes.spi.LoweringTool; 55 import org.graalvm.compiler.phases.OptimisticOptimizations; 56 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 57 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 58 import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; 59 import org.graalvm.compiler.phases.common.LoweringPhase; 60 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 61 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; 62 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; 63 import org.graalvm.compiler.phases.tiers.HighTierContext; 64 import org.graalvm.compiler.phases.tiers.MidTierContext; 65 import org.graalvm.util.EconomicMap; 66 import org.graalvm.word.LocationIdentity; 67 68 import jdk.vm.ci.meta.ResolvedJavaField; 69 70 /** 71 * The following tests validate the write barrier verification phase. For every tested snippet, an 72 * array of write barrier indices and the total write barrier number are passed as parameters. The 73 * indices denote the barriers that will be manually removed. The write barrier verification phase 74 * runs after the write barrier removal and depending on the result an assertion might be generated. 75 * The tests anticipate the presence or not of an assertion generated by the verification phase. 76 */ 77 public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { 78 79 public static int barrierIndex; 80 81 private final GraalHotSpotVMConfig config = runtime().getVMConfig(); 82 83 public static class Container { 84 85 public Container a; 86 public Container b; 630 System.arraycopy(a, 0, b, 0, a.length); 631 } 632 633 @Test 634 public void test61() { 635 GraphPredicate checkForUnsafeArrayCopy = graph -> graph.getNodes().filter(UnsafeArrayCopyNode.class).count() > 0 ? 1 : 0; 636 testPredicate("test13Snippet", checkForUnsafeArrayCopy, new int[]{}); 637 } 638 639 private interface GraphPredicate { 640 int apply(StructuredGraph graph); 641 } 642 643 private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) { 644 GraphPredicate noCheck = noArg -> expectedBarriers; 645 testPredicate(snippet, noCheck, removedBarrierIndices); 646 } 647 648 @SuppressWarnings("try") 649 private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) { 650 try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { 651 final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); 652 HighTierContext highTierContext = getDefaultHighTierContext(); 653 new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); 654 655 MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 656 657 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); 658 new GuardLoweringPhase().apply(graph, midTierContext); 659 new LoopSafepointInsertionPhase().apply(graph); 660 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext); 661 662 new WriteBarrierAdditionPhase(config).apply(graph); 663 664 int barriers = 0; 665 // First, the total number of expected barriers is checked. 666 if (config.useG1GC) { 667 barriers = graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count() + 668 graph.getNodes().filter(G1ArrayRangePreWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePostWriteBarrier.class).count(); 669 Assert.assertTrue(expectedBarriers.apply(graph) * 2 == barriers); 670 } else { 671 barriers = graph.getNodes().filter(SerialWriteBarrier.class).count() + graph.getNodes().filter(SerialArrayRangeWriteBarrier.class).count(); 708 } 709 return false; 710 } 711 712 @Override 713 protected EconomicMap<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) { 714 return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; 715 } 716 717 @Override 718 protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) { 719 return false; 720 } 721 722 @Override 723 protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) { 724 return false; 725 } 726 }; 727 728 DebugConfig debugConfig = DebugScope.getConfig(); 729 DebugConfig fixedConfig = debugConfig == null ? null 730 : Debug.fixedConfig(debugConfig.getOptions(), 0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); 731 try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { 732 ReentrantNodeIterator.apply(closure, graph.start(), false); 733 new WriteBarrierVerificationPhase(config).apply(graph); 734 } catch (AssertionError error) { 735 /* 736 * Catch assertion, test for expected one and re-throw in order to validate unit 737 * test. 738 */ 739 Assert.assertTrue(error.getMessage().contains("Write barrier must be present")); 740 throw error; 741 } 742 } catch (Throwable e) { 743 throw Debug.handle(e); 744 } 745 } 746 } | 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.hotspot.test; 24 25 import java.util.List; 26 27 import org.graalvm.compiler.debug.DebugCloseable; 28 import org.graalvm.compiler.debug.DebugContext; 29 import org.graalvm.compiler.debug.DebugContext.Scope; 30 import org.graalvm.compiler.debug.DebugDumpScope; 31 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 32 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; 33 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; 34 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; 35 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; 36 import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; 37 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; 38 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 39 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; 40 import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopyNode; 41 import org.graalvm.compiler.nodes.AbstractBeginNode; 42 import org.graalvm.compiler.nodes.AbstractMergeNode; 43 import org.graalvm.compiler.nodes.FieldLocationIdentity; 44 import org.graalvm.compiler.nodes.FixedNode; 45 import org.graalvm.compiler.nodes.FixedWithNextNode; 46 import org.graalvm.compiler.nodes.LoopBeginNode; 47 import org.graalvm.compiler.nodes.LoopExitNode; 48 import org.graalvm.compiler.nodes.StructuredGraph; 49 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 50 import org.graalvm.compiler.nodes.memory.WriteNode; 51 import org.graalvm.compiler.nodes.spi.LoweringTool; 52 import org.graalvm.compiler.phases.OptimisticOptimizations; 53 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 54 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 55 import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; 56 import org.graalvm.compiler.phases.common.LoweringPhase; 57 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 58 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; 59 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; 60 import org.graalvm.compiler.phases.tiers.HighTierContext; 61 import org.graalvm.compiler.phases.tiers.MidTierContext; 62 import org.graalvm.util.EconomicMap; 63 import org.graalvm.word.LocationIdentity; 64 import org.junit.Assert; 65 import org.junit.Test; 66 67 import jdk.vm.ci.meta.ResolvedJavaField; 68 69 /** 70 * The following tests validate the write barrier verification phase. For every tested snippet, an 71 * array of write barrier indices and the total write barrier number are passed as parameters. The 72 * indices denote the barriers that will be manually removed. The write barrier verification phase 73 * runs after the write barrier removal and depending on the result an assertion might be generated. 74 * The tests anticipate the presence or not of an assertion generated by the verification phase. 75 */ 76 public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { 77 78 public static int barrierIndex; 79 80 private final GraalHotSpotVMConfig config = runtime().getVMConfig(); 81 82 public static class Container { 83 84 public Container a; 85 public Container b; 629 System.arraycopy(a, 0, b, 0, a.length); 630 } 631 632 @Test 633 public void test61() { 634 GraphPredicate checkForUnsafeArrayCopy = graph -> graph.getNodes().filter(UnsafeArrayCopyNode.class).count() > 0 ? 1 : 0; 635 testPredicate("test13Snippet", checkForUnsafeArrayCopy, new int[]{}); 636 } 637 638 private interface GraphPredicate { 639 int apply(StructuredGraph graph); 640 } 641 642 private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) { 643 GraphPredicate noCheck = noArg -> expectedBarriers; 644 testPredicate(snippet, noCheck, removedBarrierIndices); 645 } 646 647 @SuppressWarnings("try") 648 private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) { 649 DebugContext debug = getDebugContext(); 650 try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { 651 final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); 652 HighTierContext highTierContext = getDefaultHighTierContext(); 653 new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); 654 655 MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 656 657 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); 658 new GuardLoweringPhase().apply(graph, midTierContext); 659 new LoopSafepointInsertionPhase().apply(graph); 660 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext); 661 662 new WriteBarrierAdditionPhase(config).apply(graph); 663 664 int barriers = 0; 665 // First, the total number of expected barriers is checked. 666 if (config.useG1GC) { 667 barriers = graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count() + 668 graph.getNodes().filter(G1ArrayRangePreWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePostWriteBarrier.class).count(); 669 Assert.assertTrue(expectedBarriers.apply(graph) * 2 == barriers); 670 } else { 671 barriers = graph.getNodes().filter(SerialWriteBarrier.class).count() + graph.getNodes().filter(SerialArrayRangeWriteBarrier.class).count(); 708 } 709 return false; 710 } 711 712 @Override 713 protected EconomicMap<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) { 714 return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; 715 } 716 717 @Override 718 protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) { 719 return false; 720 } 721 722 @Override 723 protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) { 724 return false; 725 } 726 }; 727 728 try (Scope disabled = debug.disable()) { 729 ReentrantNodeIterator.apply(closure, graph.start(), false); 730 new WriteBarrierVerificationPhase(config).apply(graph); 731 } catch (AssertionError error) { 732 /* 733 * Catch assertion, test for expected one and re-throw in order to validate unit 734 * test. 735 */ 736 Assert.assertTrue(error.getMessage().contains("Write barrier must be present")); 737 throw error; 738 } 739 } catch (Throwable e) { 740 throw debug.handle(e); 741 } 742 } 743 } |