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