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