1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   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 java.util.Map;
  27 
  28 import org.junit.Assert;
  29 import org.junit.Test;
  30 
  31 import org.graalvm.compiler.core.common.LocationIdentity;
  32 import org.graalvm.compiler.debug.Debug;
  33 import org.graalvm.compiler.debug.Debug.Scope;
  34 import org.graalvm.compiler.debug.DebugConfig;
  35 import org.graalvm.compiler.debug.DebugConfigScope;
  36 import org.graalvm.compiler.debug.DebugDumpScope;
  37 import org.graalvm.compiler.debug.internal.DebugScope;
  38 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  39 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
  40 import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
  41 import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
  42 import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
  43 import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier;
  44 import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
  45 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
  46 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
  47 import org.graalvm.compiler.hotspot.replacements.arraycopy.UnsafeArrayCopyNode;
  48 import org.graalvm.compiler.nodes.AbstractBeginNode;
  49 import org.graalvm.compiler.nodes.AbstractMergeNode;
  50 import org.graalvm.compiler.nodes.FieldLocationIdentity;
  51 import org.graalvm.compiler.nodes.FixedNode;
  52 import org.graalvm.compiler.nodes.FixedWithNextNode;
  53 import org.graalvm.compiler.nodes.LoopBeginNode;
  54 import org.graalvm.compiler.nodes.LoopExitNode;
  55 import org.graalvm.compiler.nodes.StructuredGraph;
  56 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  57 import org.graalvm.compiler.nodes.memory.WriteNode;
  58 import org.graalvm.compiler.nodes.spi.LoweringTool;
  59 import org.graalvm.compiler.phases.OptimisticOptimizations;
  60 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  61 import org.graalvm.compiler.phases.common.GuardLoweringPhase;
  62 import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
  63 import org.graalvm.compiler.phases.common.LoweringPhase;
  64 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
  65 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
  66 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
  67 import org.graalvm.compiler.phases.tiers.HighTierContext;
  68 import org.graalvm.compiler.phases.tiers.MidTierContext;
  69 
  70 import jdk.vm.ci.meta.ResolvedJavaField;
  71 
  72 /**
  73  * The following tests validate the write barrier verification phase. For every tested snippet, an
  74  * array of write barrier indices and the total write barrier number are passed as parameters. The
  75  * indices denote the barriers that will be manually removed. The write barrier verification phase
  76  * runs after the write barrier removal and depending on the result an assertion might be generated.
  77  * The tests anticipate the presence or not of an assertion generated by the verification phase.
  78  */
  79 public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest {
  80 
  81     public static int barrierIndex;
  82 
  83     private final GraalHotSpotVMConfig config = runtime().getVMConfig();
  84 
  85     public static class Container {
  86 
  87         public Container a;
  88         public Container b;
  89     }
  90 
  91     private static native void safepoint();
  92 
  93     public static void test1Snippet(Container main) {
  94         Container temp1 = new Container();
  95         Container temp2 = new Container();
  96         barrierIndex = 0;
  97         safepoint();
  98         barrierIndex = 1;
  99         main.a = temp1;
 100         safepoint();
 101         barrierIndex = 2;
 102         main.b = temp2;
 103         safepoint();
 104     }
 105 
 106     @Test(expected = AssertionError.class)
 107     public void test1() {
 108         test("test1Snippet", 2, new int[]{1});
 109     }
 110 
 111     @Test(expected = AssertionError.class)
 112     public void test2() {
 113         test("test1Snippet", 2, new int[]{2});
 114     }
 115 
 116     public static void test2Snippet(Container main) {
 117         Container temp1 = new Container();
 118         Container temp2 = new Container();
 119         barrierIndex = 0;
 120         safepoint();
 121         barrierIndex = 1;
 122         main.a = temp1;
 123         barrierIndex = 2;
 124         main.b = temp2;
 125         safepoint();
 126     }
 127 
 128     @Test(expected = AssertionError.class)
 129     public void test3() {
 130         test("test2Snippet", 2, new int[]{1});
 131     }
 132 
 133     @Test
 134     public void test4() {
 135         test("test2Snippet", 2, new int[]{2});
 136     }
 137 
 138     public static void test3Snippet(Container main, boolean test) {
 139         Container temp1 = new Container();
 140         Container temp2 = new Container();
 141         barrierIndex = 0;
 142         safepoint();
 143         for (int i = 0; i < 10; i++) {
 144             if (test) {
 145                 barrierIndex = 1;
 146                 main.a = temp1;
 147                 barrierIndex = 2;
 148                 main.b = temp2;
 149             } else {
 150                 barrierIndex = 3;
 151                 main.a = temp1;
 152                 barrierIndex = 4;
 153                 main.b = temp2;
 154             }
 155         }
 156     }
 157 
 158     @Test(expected = AssertionError.class)
 159     public void test5() {
 160         test("test3Snippet", 4, new int[]{1, 2});
 161     }
 162 
 163     @Test(expected = AssertionError.class)
 164     public void test6() {
 165         test("test3Snippet", 4, new int[]{3, 4});
 166     }
 167 
 168     @Test(expected = AssertionError.class)
 169     public void test7() {
 170         test("test3Snippet", 4, new int[]{1});
 171     }
 172 
 173     @Test
 174     public void test8() {
 175         test("test3Snippet", 4, new int[]{2});
 176     }
 177 
 178     @Test(expected = AssertionError.class)
 179     public void test9() {
 180         test("test3Snippet", 4, new int[]{3});
 181     }
 182 
 183     @Test
 184     public void test10() {
 185         test("test3Snippet", 4, new int[]{4});
 186     }
 187 
 188     public static void test4Snippet(Container main, boolean test) {
 189         Container temp1 = new Container();
 190         Container temp2 = new Container();
 191         safepoint();
 192         barrierIndex = 1;
 193         main.a = temp1;
 194         for (int i = 0; i < 10; i++) {
 195             if (test) {
 196                 barrierIndex = 2;
 197                 main.a = temp1;
 198                 barrierIndex = 3;
 199                 main.b = temp2;
 200             } else {
 201                 barrierIndex = 4;
 202                 main.a = temp2;
 203                 barrierIndex = 5;
 204                 main.b = temp1;
 205             }
 206         }
 207     }
 208 
 209     @Test(expected = AssertionError.class)
 210     public void test11() {
 211         test("test4Snippet", 5, new int[]{2, 3});
 212     }
 213 
 214     @Test(expected = AssertionError.class)
 215     public void test12() {
 216         test("test4Snippet", 5, new int[]{4, 5});
 217     }
 218 
 219     @Test(expected = AssertionError.class)
 220     public void test13() {
 221         test("test4Snippet", 5, new int[]{1});
 222     }
 223 
 224     public static void test5Snippet(Container main) {
 225         Container temp1 = new Container();
 226         Container temp2 = new Container();
 227         safepoint();
 228         barrierIndex = 1;
 229         main.a = temp1;
 230         if (main.a == main.b) {
 231             barrierIndex = 2;
 232             main.a = temp1;
 233             barrierIndex = 3;
 234             main.b = temp2;
 235         } else {
 236             barrierIndex = 4;
 237             main.a = temp2;
 238             barrierIndex = 5;
 239             main.b = temp1;
 240         }
 241         safepoint();
 242     }
 243 
 244     @Test(expected = AssertionError.class)
 245     public void test14() {
 246         test("test5Snippet", 5, new int[]{1});
 247     }
 248 
 249     @Test
 250     public void test15() {
 251         test("test5Snippet", 5, new int[]{2});
 252     }
 253 
 254     @Test
 255     public void test16() {
 256         test("test5Snippet", 5, new int[]{4});
 257     }
 258 
 259     @Test
 260     public void test17() {
 261         test("test5Snippet", 5, new int[]{3});
 262     }
 263 
 264     @Test
 265     public void test18() {
 266         test("test5Snippet", 5, new int[]{5});
 267     }
 268 
 269     @Test
 270     public void test19() {
 271         test("test5Snippet", 5, new int[]{2, 3});
 272     }
 273 
 274     @Test
 275     public void test20() {
 276         test("test5Snippet", 5, new int[]{4, 5});
 277     }
 278 
 279     public static void test6Snippet(Container main, boolean test) {
 280         Container temp1 = new Container();
 281         Container temp2 = new Container();
 282         safepoint();
 283         barrierIndex = 1;
 284         main.a = temp1;
 285         if (test) {
 286             barrierIndex = 2;
 287             main.a = temp1;
 288             barrierIndex = 3;
 289             main.b = temp1.a.a;
 290         } else {
 291             barrierIndex = 4;
 292             main.a = temp2;
 293             barrierIndex = 5;
 294             main.b = temp2.a.a;
 295         }
 296         safepoint();
 297     }
 298 
 299     @Test(expected = AssertionError.class)
 300     public void test21() {
 301         test("test6Snippet", 5, new int[]{1});
 302     }
 303 
 304     @Test(expected = AssertionError.class)
 305     public void test22() {
 306         test("test6Snippet", 5, new int[]{1, 2});
 307     }
 308 
 309     @Test(expected = AssertionError.class)
 310     public void test23() {
 311         test("test6Snippet", 5, new int[]{3});
 312     }
 313 
 314     @Test
 315     public void test24() {
 316         test("test6Snippet", 5, new int[]{4});
 317     }
 318 
 319     public static void test7Snippet(Container main, boolean test) {
 320         Container temp1 = new Container();
 321         Container temp2 = new Container();
 322         safepoint();
 323         barrierIndex = 1;
 324         main.a = temp1;
 325         if (test) {
 326             barrierIndex = 2;
 327             main.a = temp1;
 328         }
 329         barrierIndex = 3;
 330         main.b = temp2;
 331         safepoint();
 332     }
 333 
 334     @Test
 335     public void test25() {
 336         test("test7Snippet", 3, new int[]{2});
 337     }
 338 
 339     @Test
 340     public void test26() {
 341         test("test7Snippet", 3, new int[]{3});
 342     }
 343 
 344     @Test
 345     public void test27() {
 346         test("test7Snippet", 3, new int[]{2, 3});
 347     }
 348 
 349     @Test(expected = AssertionError.class)
 350     public void test28() {
 351         test("test7Snippet", 3, new int[]{1});
 352     }
 353 
 354     public static void test8Snippet(Container main, boolean test) {
 355         Container temp1 = new Container();
 356         Container temp2 = new Container();
 357         safepoint();
 358         if (test) {
 359             barrierIndex = 1;
 360             main.a = temp1;
 361         }
 362         barrierIndex = 2;
 363         main.b = temp2;
 364         safepoint();
 365     }
 366 
 367     @Test(expected = AssertionError.class)
 368     public void test29() {
 369         test("test8Snippet", 2, new int[]{1});
 370     }
 371 
 372     @Test(expected = AssertionError.class)
 373     public void test30() {
 374         test("test8Snippet", 2, new int[]{2});
 375     }
 376 
 377     @Test(expected = AssertionError.class)
 378     public void test31() {
 379         test("test8Snippet", 2, new int[]{1, 2});
 380     }
 381 
 382     public static void test9Snippet(Container main1, Container main2, boolean test) {
 383         Container temp1 = new Container();
 384         Container temp2 = new Container();
 385         safepoint();
 386         if (test) {
 387             barrierIndex = 1;
 388             main1.a = temp1;
 389         } else {
 390             barrierIndex = 2;
 391             main2.a = temp1;
 392         }
 393         barrierIndex = 3;
 394         main1.b = temp2;
 395         barrierIndex = 4;
 396         main2.b = temp2;
 397         safepoint();
 398     }
 399 
 400     @Test(expected = AssertionError.class)
 401     public void test32() {
 402         test("test9Snippet", 4, new int[]{1});
 403     }
 404 
 405     @Test(expected = AssertionError.class)
 406     public void test33() {
 407         test("test9Snippet", 4, new int[]{2});
 408     }
 409 
 410     @Test(expected = AssertionError.class)
 411     public void test34() {
 412         test("test9Snippet", 4, new int[]{3});
 413     }
 414 
 415     @Test(expected = AssertionError.class)
 416     public void test35() {
 417         test("test9Snippet", 4, new int[]{4});
 418     }
 419 
 420     @Test(expected = AssertionError.class)
 421     public void test36() {
 422         test("test9Snippet", 4, new int[]{1, 2});
 423     }
 424 
 425     @Test(expected = AssertionError.class)
 426     public void test37() {
 427         test("test9Snippet", 4, new int[]{3, 4});
 428     }
 429 
 430     public static void test10Snippet(Container main1, Container main2, boolean test) {
 431         Container temp1 = new Container();
 432         Container temp2 = new Container();
 433         safepoint();
 434         if (test) {
 435             barrierIndex = 1;
 436             main1.a = temp1;
 437             barrierIndex = 2;
 438             main2.a = temp2;
 439         } else {
 440             barrierIndex = 3;
 441             main2.a = temp1;
 442         }
 443         barrierIndex = 4;
 444         main1.b = temp2;
 445         barrierIndex = 5;
 446         main2.b = temp2;
 447         safepoint();
 448     }
 449 
 450     @Test(expected = AssertionError.class)
 451     public void test38() {
 452         test("test10Snippet", 5, new int[]{1});
 453     }
 454 
 455     @Test(expected = AssertionError.class)
 456     public void test39() {
 457         test("test10Snippet", 5, new int[]{2});
 458     }
 459 
 460     @Test(expected = AssertionError.class)
 461     public void test40() {
 462         test("test10Snippet", 5, new int[]{3});
 463     }
 464 
 465     @Test(expected = AssertionError.class)
 466     public void test41() {
 467         test("test10Snippet", 5, new int[]{4});
 468     }
 469 
 470     @Test
 471     public void test42() {
 472         test("test10Snippet", 5, new int[]{5});
 473     }
 474 
 475     @Test(expected = AssertionError.class)
 476     public void test43() {
 477         test("test10Snippet", 5, new int[]{1, 2});
 478     }
 479 
 480     @Test(expected = AssertionError.class)
 481     public void test44() {
 482         test("test10Snippet", 5, new int[]{1, 2, 3});
 483     }
 484 
 485     @Test(expected = AssertionError.class)
 486     public void test45() {
 487         test("test10Snippet", 5, new int[]{3, 4});
 488     }
 489 
 490     public static void test11Snippet(Container main1, Container main2, Container main3, boolean test) {
 491         Container temp1 = new Container();
 492         Container temp2 = new Container();
 493         safepoint();
 494         if (test) {
 495             barrierIndex = 1;
 496             main1.a = temp1;
 497             barrierIndex = 2;
 498             main3.a = temp1;
 499             if (!test) {
 500                 barrierIndex = 3;
 501                 main2.a = temp2;
 502             } else {
 503                 barrierIndex = 4;
 504                 main1.a = temp2;
 505                 barrierIndex = 5;
 506                 main3.a = temp2;
 507             }
 508         } else {
 509             barrierIndex = 6;
 510             main1.b = temp2;
 511             for (int i = 0; i < 10; i++) {
 512                 barrierIndex = 7;
 513                 main3.a = temp1;
 514             }
 515             barrierIndex = 8;
 516             main3.b = temp2;
 517         }
 518         barrierIndex = 9;
 519         main1.b = temp2;
 520         barrierIndex = 10;
 521         main2.b = temp2;
 522         barrierIndex = 11;
 523         main3.b = temp2;
 524         safepoint();
 525     }
 526 
 527     @Test(expected = AssertionError.class)
 528     public void test46() {
 529         test("test11Snippet", 11, new int[]{1});
 530     }
 531 
 532     @Test(expected = AssertionError.class)
 533     public void test47() {
 534         test("test11Snippet", 11, new int[]{2});
 535     }
 536 
 537     @Test(expected = AssertionError.class)
 538     public void test48() {
 539         test("test11Snippet", 11, new int[]{3});
 540     }
 541 
 542     @Test(expected = AssertionError.class)
 543     public void test49() {
 544         test("test11Snippet", 11, new int[]{6});
 545     }
 546 
 547     @Test(expected = AssertionError.class)
 548     public void test50() {
 549         test("test11Snippet", 11, new int[]{7});
 550     }
 551 
 552     @Test(expected = AssertionError.class)
 553     public void test51() {
 554         test("test11Snippet", 11, new int[]{8});
 555     }
 556 
 557     @Test(expected = AssertionError.class)
 558     public void test52() {
 559         test("test11Snippet", 11, new int[]{9});
 560     }
 561 
 562     @Test(expected = AssertionError.class)
 563     public void test53() {
 564         test("test11Snippet", 11, new int[]{10});
 565     }
 566 
 567     @Test
 568     public void test54() {
 569         test("test11Snippet", 11, new int[]{4});
 570     }
 571 
 572     @Test
 573     public void test55() {
 574         test("test11Snippet", 11, new int[]{5});
 575     }
 576 
 577     @Test
 578     public void test56() {
 579         test("test11Snippet", 11, new int[]{11});
 580     }
 581 
 582     public static void test12Snippet(Container main, Container main1, boolean test) {
 583         Container temp1 = new Container();
 584         Container temp2 = new Container();
 585         barrierIndex = 0;
 586         safepoint();
 587         barrierIndex = 7;
 588         main1.a = temp1;
 589         for (int i = 0; i < 10; i++) {
 590             if (test) {
 591                 barrierIndex = 1;
 592                 main.a = temp1;
 593                 barrierIndex = 2;
 594                 main.b = temp2;
 595             } else {
 596                 barrierIndex = 3;
 597                 main.a = temp1;
 598                 barrierIndex = 4;
 599                 main.b = temp2;
 600             }
 601         }
 602         barrierIndex = 5;
 603         main.a = temp1;
 604         barrierIndex = 6;
 605         main.b = temp1;
 606         barrierIndex = 8;
 607         main1.b = temp1;
 608         safepoint();
 609     }
 610 
 611     @Test(expected = AssertionError.class)
 612     public void test57() {
 613         test("test12Snippet", 8, new int[]{5});
 614     }
 615 
 616     @Test
 617     public void test58() {
 618         test("test12Snippet", 8, new int[]{6});
 619     }
 620 
 621     @Test(expected = AssertionError.class)
 622     public void test59() {
 623         test("test12Snippet", 8, new int[]{7});
 624     }
 625 
 626     @Test(expected = AssertionError.class)
 627     public void test60() {
 628         test("test12Snippet", 8, new int[]{8});
 629     }
 630 
 631     public static void test13Snippet(Object[] a, Object[] b) {
 632         System.arraycopy(a, 0, b, 0, a.length);
 633     }
 634 
 635     @Test
 636     public void test61() {
 637         GraphPredicate checkForUnsafeArrayCopy = graph -> graph.getNodes().filter(UnsafeArrayCopyNode.class).count() > 0 ? 1 : 0;
 638         testPredicate("test13Snippet", checkForUnsafeArrayCopy, new int[]{});
 639     }
 640 
 641     private interface GraphPredicate {
 642         int apply(StructuredGraph graph);
 643     }
 644 
 645     private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) {
 646         GraphPredicate noCheck = noArg -> expectedBarriers;
 647         testPredicate(snippet, noCheck, removedBarrierIndices);
 648     }
 649 
 650     @SuppressWarnings("try")
 651     private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) {
 652         try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) {
 653             final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
 654             HighTierContext highTierContext = getDefaultHighTierContext();
 655             new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext);
 656 
 657             MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
 658 
 659             new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
 660             new GuardLoweringPhase().apply(graph, midTierContext);
 661             new LoopSafepointInsertionPhase().apply(graph);
 662             new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext);
 663 
 664             new WriteBarrierAdditionPhase(config).apply(graph);
 665 
 666             int barriers = 0;
 667             // First, the total number of expected barriers is checked.
 668             if (config.useG1GC) {
 669                 barriers = graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count() +
 670                                 graph.getNodes().filter(G1ArrayRangePreWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePostWriteBarrier.class).count();
 671                 Assert.assertTrue(expectedBarriers.apply(graph) * 2 == barriers);
 672             } else {
 673                 barriers = graph.getNodes().filter(SerialWriteBarrier.class).count() + graph.getNodes().filter(SerialArrayRangeWriteBarrier.class).count();
 674                 Assert.assertTrue(expectedBarriers.apply(graph) == barriers);
 675             }
 676             ResolvedJavaField barrierIndexField = getMetaAccess().lookupJavaField(WriteBarrierVerificationTest.class.getDeclaredField("barrierIndex"));
 677             LocationIdentity barrierIdentity = new FieldLocationIdentity(barrierIndexField);
 678             // Iterate over all write nodes and remove barriers according to input indices.
 679             NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
 680 
 681                 @Override
 682                 protected Boolean processNode(FixedNode node, Boolean currentState) {
 683                     if (node instanceof WriteNode) {
 684                         WriteNode write = (WriteNode) node;
 685                         LocationIdentity obj = write.getLocationIdentity();
 686                         if (obj.equals(barrierIdentity)) {
 687                             /*
 688                              * A "barrierIndex" variable was found and is checked against the input
 689                              * barrier array.
 690                              */
 691                             if (eliminateBarrier(write.value().asJavaConstant().asInt(), removedBarrierIndices)) {
 692                                 return true;
 693                             }
 694                         }
 695                     } else if (node instanceof SerialWriteBarrier || node instanceof G1PostWriteBarrier) {
 696                         // Remove flagged write barriers.
 697                         if (currentState) {
 698                             graph.removeFixed(((FixedWithNextNode) node));
 699                             return false;
 700                         }
 701                     }
 702                     return currentState;
 703                 }
 704 
 705                 private boolean eliminateBarrier(int index, int[] map) {
 706                     for (int i = 0; i < map.length; i++) {
 707                         if (map[i] == index) {
 708                             return true;
 709                         }
 710                     }
 711                     return false;
 712                 }
 713 
 714                 @Override
 715                 protected Map<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) {
 716                     return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
 717                 }
 718 
 719                 @Override
 720                 protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) {
 721                     return false;
 722                 }
 723 
 724                 @Override
 725                 protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
 726                     return false;
 727                 }
 728             };
 729 
 730             DebugConfig debugConfig = DebugScope.getConfig();
 731             DebugConfig fixedConfig = debugConfig == null ? null
 732                             : Debug.fixedConfig(0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
 733             try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
 734                 ReentrantNodeIterator.apply(closure, graph.start(), false);
 735                 new WriteBarrierVerificationPhase(config).apply(graph);
 736             } catch (AssertionError error) {
 737                 /*
 738                  * Catch assertion, test for expected one and re-throw in order to validate unit
 739                  * test.
 740                  */
 741                 Assert.assertTrue(error.getMessage().contains("Write barrier must be present"));
 742                 throw error;
 743             }
 744         } catch (Throwable e) {
 745             throw Debug.handle(e);
 746         }
 747     }
 748 }