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 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;
  87     }
  88 
  89     private static native void safepoint();
  90 
  91     public static void test1Snippet(Container main) {
  92         Container temp1 = new Container();
  93         Container temp2 = new Container();
  94         barrierIndex = 0;
  95         safepoint();
  96         barrierIndex = 1;
  97         main.a = temp1;
  98         safepoint();
  99         barrierIndex = 2;
 100         main.b = temp2;
 101         safepoint();
 102     }
 103 
 104     @Test(expected = AssertionError.class)
 105     public void test1() {
 106         test("test1Snippet", 2, new int[]{1});
 107     }
 108 
 109     @Test(expected = AssertionError.class)
 110     public void test2() {
 111         test("test1Snippet", 2, new int[]{2});
 112     }
 113 
 114     public static void test2Snippet(Container main) {
 115         Container temp1 = new Container();
 116         Container temp2 = new Container();
 117         barrierIndex = 0;
 118         safepoint();
 119         barrierIndex = 1;
 120         main.a = temp1;
 121         barrierIndex = 2;
 122         main.b = temp2;
 123         safepoint();
 124     }
 125 
 126     @Test(expected = AssertionError.class)
 127     public void test3() {
 128         test("test2Snippet", 2, new int[]{1});
 129     }
 130 
 131     @Test
 132     public void test4() {
 133         test("test2Snippet", 2, new int[]{2});
 134     }
 135 
 136     public static void test3Snippet(Container main, boolean test) {
 137         Container temp1 = new Container();
 138         Container temp2 = new Container();
 139         barrierIndex = 0;
 140         safepoint();
 141         for (int i = 0; i < 10; i++) {
 142             if (test) {
 143                 barrierIndex = 1;
 144                 main.a = temp1;
 145                 barrierIndex = 2;
 146                 main.b = temp2;
 147             } else {
 148                 barrierIndex = 3;
 149                 main.a = temp1;
 150                 barrierIndex = 4;
 151                 main.b = temp2;
 152             }
 153         }
 154     }
 155 
 156     @Test(expected = AssertionError.class)
 157     public void test5() {
 158         test("test3Snippet", 4, new int[]{1, 2});
 159     }
 160 
 161     @Test(expected = AssertionError.class)
 162     public void test6() {
 163         test("test3Snippet", 4, new int[]{3, 4});
 164     }
 165 
 166     @Test(expected = AssertionError.class)
 167     public void test7() {
 168         test("test3Snippet", 4, new int[]{1});
 169     }
 170 
 171     @Test
 172     public void test8() {
 173         test("test3Snippet", 4, new int[]{2});
 174     }
 175 
 176     @Test(expected = AssertionError.class)
 177     public void test9() {
 178         test("test3Snippet", 4, new int[]{3});
 179     }
 180 
 181     @Test
 182     public void test10() {
 183         test("test3Snippet", 4, new int[]{4});
 184     }
 185 
 186     public static void test4Snippet(Container main, boolean test) {
 187         Container temp1 = new Container();
 188         Container temp2 = new Container();
 189         safepoint();
 190         barrierIndex = 1;
 191         main.a = temp1;
 192         for (int i = 0; i < 10; i++) {
 193             if (test) {
 194                 barrierIndex = 2;
 195                 main.a = temp1;
 196                 barrierIndex = 3;
 197                 main.b = temp2;
 198             } else {
 199                 barrierIndex = 4;
 200                 main.a = temp2;
 201                 barrierIndex = 5;
 202                 main.b = temp1;
 203             }
 204         }
 205     }
 206 
 207     @Test(expected = AssertionError.class)
 208     public void test11() {
 209         test("test4Snippet", 5, new int[]{2, 3});
 210     }
 211 
 212     @Test(expected = AssertionError.class)
 213     public void test12() {
 214         test("test4Snippet", 5, new int[]{4, 5});
 215     }
 216 
 217     @Test(expected = AssertionError.class)
 218     public void test13() {
 219         test("test4Snippet", 5, new int[]{1});
 220     }
 221 
 222     public static void test5Snippet(Container main) {
 223         Container temp1 = new Container();
 224         Container temp2 = new Container();
 225         safepoint();
 226         barrierIndex = 1;
 227         main.a = temp1;
 228         if (main.a == main.b) {
 229             barrierIndex = 2;
 230             main.a = temp1;
 231             barrierIndex = 3;
 232             main.b = temp2;
 233         } else {
 234             barrierIndex = 4;
 235             main.a = temp2;
 236             barrierIndex = 5;
 237             main.b = temp1;
 238         }
 239         safepoint();
 240     }
 241 
 242     @Test(expected = AssertionError.class)
 243     public void test14() {
 244         test("test5Snippet", 5, new int[]{1});
 245     }
 246 
 247     @Test
 248     public void test15() {
 249         test("test5Snippet", 5, new int[]{2});
 250     }
 251 
 252     @Test
 253     public void test16() {
 254         test("test5Snippet", 5, new int[]{4});
 255     }
 256 
 257     @Test
 258     public void test17() {
 259         test("test5Snippet", 5, new int[]{3});
 260     }
 261 
 262     @Test
 263     public void test18() {
 264         test("test5Snippet", 5, new int[]{5});
 265     }
 266 
 267     @Test
 268     public void test19() {
 269         test("test5Snippet", 5, new int[]{2, 3});
 270     }
 271 
 272     @Test
 273     public void test20() {
 274         test("test5Snippet", 5, new int[]{4, 5});
 275     }
 276 
 277     public static void test6Snippet(Container main, boolean test) {
 278         Container temp1 = new Container();
 279         Container temp2 = new Container();
 280         safepoint();
 281         barrierIndex = 1;
 282         main.a = temp1;
 283         if (test) {
 284             barrierIndex = 2;
 285             main.a = temp1;
 286             barrierIndex = 3;
 287             main.b = temp1.a.a;
 288         } else {
 289             barrierIndex = 4;
 290             main.a = temp2;
 291             barrierIndex = 5;
 292             main.b = temp2.a.a;
 293         }
 294         safepoint();
 295     }
 296 
 297     @Test(expected = AssertionError.class)
 298     public void test21() {
 299         test("test6Snippet", 5, new int[]{1});
 300     }
 301 
 302     @Test(expected = AssertionError.class)
 303     public void test22() {
 304         test("test6Snippet", 5, new int[]{1, 2});
 305     }
 306 
 307     @Test
 308     public void test23() {
 309         test("test6Snippet", 5, new int[]{3});
 310     }
 311 
 312     @Test
 313     public void test24() {
 314         test("test6Snippet", 5, new int[]{4});
 315     }
 316 
 317     public static void test7Snippet(Container main, boolean test) {
 318         Container temp1 = new Container();
 319         Container temp2 = new Container();
 320         safepoint();
 321         barrierIndex = 1;
 322         main.a = temp1;
 323         if (test) {
 324             barrierIndex = 2;
 325             main.a = temp1;
 326         }
 327         barrierIndex = 3;
 328         main.b = temp2;
 329         safepoint();
 330     }
 331 
 332     @Test
 333     public void test25() {
 334         test("test7Snippet", 3, new int[]{2});
 335     }
 336 
 337     @Test
 338     public void test26() {
 339         test("test7Snippet", 3, new int[]{3});
 340     }
 341 
 342     @Test
 343     public void test27() {
 344         test("test7Snippet", 3, new int[]{2, 3});
 345     }
 346 
 347     @Test(expected = AssertionError.class)
 348     public void test28() {
 349         test("test7Snippet", 3, new int[]{1});
 350     }
 351 
 352     public static void test8Snippet(Container main, boolean test) {
 353         Container temp1 = new Container();
 354         Container temp2 = new Container();
 355         safepoint();
 356         if (test) {
 357             barrierIndex = 1;
 358             main.a = temp1;
 359         }
 360         barrierIndex = 2;
 361         main.b = temp2;
 362         safepoint();
 363     }
 364 
 365     @Test(expected = AssertionError.class)
 366     public void test29() {
 367         test("test8Snippet", 2, new int[]{1});
 368     }
 369 
 370     @Test(expected = AssertionError.class)
 371     public void test30() {
 372         test("test8Snippet", 2, new int[]{2});
 373     }
 374 
 375     @Test(expected = AssertionError.class)
 376     public void test31() {
 377         test("test8Snippet", 2, new int[]{1, 2});
 378     }
 379 
 380     public static void test9Snippet(Container main1, Container main2, boolean test) {
 381         Container temp1 = new Container();
 382         Container temp2 = new Container();
 383         safepoint();
 384         if (test) {
 385             barrierIndex = 1;
 386             main1.a = temp1;
 387         } else {
 388             barrierIndex = 2;
 389             main2.a = temp1;
 390         }
 391         barrierIndex = 3;
 392         main1.b = temp2;
 393         barrierIndex = 4;
 394         main2.b = temp2;
 395         safepoint();
 396     }
 397 
 398     @Test(expected = AssertionError.class)
 399     public void test32() {
 400         test("test9Snippet", 4, new int[]{1});
 401     }
 402 
 403     @Test(expected = AssertionError.class)
 404     public void test33() {
 405         test("test9Snippet", 4, new int[]{2});
 406     }
 407 
 408     @Test(expected = AssertionError.class)
 409     public void test34() {
 410         test("test9Snippet", 4, new int[]{3});
 411     }
 412 
 413     @Test(expected = AssertionError.class)
 414     public void test35() {
 415         test("test9Snippet", 4, new int[]{4});
 416     }
 417 
 418     @Test(expected = AssertionError.class)
 419     public void test36() {
 420         test("test9Snippet", 4, new int[]{1, 2});
 421     }
 422 
 423     @Test(expected = AssertionError.class)
 424     public void test37() {
 425         test("test9Snippet", 4, new int[]{3, 4});
 426     }
 427 
 428     public static void test10Snippet(Container main1, Container main2, boolean test) {
 429         Container temp1 = new Container();
 430         Container temp2 = new Container();
 431         safepoint();
 432         if (test) {
 433             barrierIndex = 1;
 434             main1.a = temp1;
 435             barrierIndex = 2;
 436             main2.a = temp2;
 437         } else {
 438             barrierIndex = 3;
 439             main2.a = temp1;
 440         }
 441         barrierIndex = 4;
 442         main1.b = temp2;
 443         barrierIndex = 5;
 444         main2.b = temp2;
 445         safepoint();
 446     }
 447 
 448     @Test(expected = AssertionError.class)
 449     public void test38() {
 450         test("test10Snippet", 5, new int[]{1});
 451     }
 452 
 453     @Test(expected = AssertionError.class)
 454     public void test39() {
 455         test("test10Snippet", 5, new int[]{2});
 456     }
 457 
 458     @Test(expected = AssertionError.class)
 459     public void test40() {
 460         test("test10Snippet", 5, new int[]{3});
 461     }
 462 
 463     @Test(expected = AssertionError.class)
 464     public void test41() {
 465         test("test10Snippet", 5, new int[]{4});
 466     }
 467 
 468     @Test
 469     public void test42() {
 470         test("test10Snippet", 5, new int[]{5});
 471     }
 472 
 473     @Test(expected = AssertionError.class)
 474     public void test43() {
 475         test("test10Snippet", 5, new int[]{1, 2});
 476     }
 477 
 478     @Test(expected = AssertionError.class)
 479     public void test44() {
 480         test("test10Snippet", 5, new int[]{1, 2, 3});
 481     }
 482 
 483     @Test(expected = AssertionError.class)
 484     public void test45() {
 485         test("test10Snippet", 5, new int[]{3, 4});
 486     }
 487 
 488     public static void test11Snippet(Container main1, Container main2, Container main3, boolean test) {
 489         Container temp1 = new Container();
 490         Container temp2 = new Container();
 491         safepoint();
 492         if (test) {
 493             barrierIndex = 1;
 494             main1.a = temp1;
 495             barrierIndex = 2;
 496             main3.a = temp1;
 497             if (!test) {
 498                 barrierIndex = 3;
 499                 main2.a = temp2;
 500             } else {
 501                 barrierIndex = 4;
 502                 main1.a = temp2;
 503                 barrierIndex = 5;
 504                 main3.a = temp2;
 505             }
 506         } else {
 507             barrierIndex = 6;
 508             main1.b = temp2;
 509             for (int i = 0; i < 10; i++) {
 510                 barrierIndex = 7;
 511                 main3.a = temp1;
 512             }
 513             barrierIndex = 8;
 514             main3.b = temp2;
 515         }
 516         barrierIndex = 9;
 517         main1.b = temp2;
 518         barrierIndex = 10;
 519         main2.b = temp2;
 520         barrierIndex = 11;
 521         main3.b = temp2;
 522         safepoint();
 523     }
 524 
 525     @Test(expected = AssertionError.class)
 526     public void test46() {
 527         test("test11Snippet", 11, new int[]{1});
 528     }
 529 
 530     @Test(expected = AssertionError.class)
 531     public void test47() {
 532         test("test11Snippet", 11, new int[]{2});
 533     }
 534 
 535     @Test(expected = AssertionError.class)
 536     public void test48() {
 537         test("test11Snippet", 11, new int[]{3});
 538     }
 539 
 540     @Test(expected = AssertionError.class)
 541     public void test49() {
 542         test("test11Snippet", 11, new int[]{6});
 543     }
 544 
 545     @Test(expected = AssertionError.class)
 546     public void test50() {
 547         test("test11Snippet", 11, new int[]{7});
 548     }
 549 
 550     @Test(expected = AssertionError.class)
 551     public void test51() {
 552         test("test11Snippet", 11, new int[]{8});
 553     }
 554 
 555     @Test(expected = AssertionError.class)
 556     public void test52() {
 557         test("test11Snippet", 11, new int[]{9});
 558     }
 559 
 560     @Test(expected = AssertionError.class)
 561     public void test53() {
 562         test("test11Snippet", 11, new int[]{10});
 563     }
 564 
 565     @Test
 566     public void test54() {
 567         test("test11Snippet", 11, new int[]{4});
 568     }
 569 
 570     @Test
 571     public void test55() {
 572         test("test11Snippet", 11, new int[]{5});
 573     }
 574 
 575     @Test
 576     public void test56() {
 577         test("test11Snippet", 11, new int[]{11});
 578     }
 579 
 580     public static void test12Snippet(Container main, Container main1, boolean test) {
 581         Container temp1 = new Container();
 582         Container temp2 = new Container();
 583         barrierIndex = 0;
 584         safepoint();
 585         barrierIndex = 7;
 586         main1.a = temp1;
 587         for (int i = 0; i < 10; i++) {
 588             if (test) {
 589                 barrierIndex = 1;
 590                 main.a = temp1;
 591                 barrierIndex = 2;
 592                 main.b = temp2;
 593             } else {
 594                 barrierIndex = 3;
 595                 main.a = temp1;
 596                 barrierIndex = 4;
 597                 main.b = temp2;
 598             }
 599         }
 600         barrierIndex = 5;
 601         main.a = temp1;
 602         barrierIndex = 6;
 603         main.b = temp1;
 604         barrierIndex = 8;
 605         main1.b = temp1;
 606         safepoint();
 607     }
 608 
 609     @Test(expected = AssertionError.class)
 610     public void test57() {
 611         test("test12Snippet", 8, new int[]{5});
 612     }
 613 
 614     @Test
 615     public void test58() {
 616         test("test12Snippet", 8, new int[]{6});
 617     }
 618 
 619     @Test(expected = AssertionError.class)
 620     public void test59() {
 621         test("test12Snippet", 8, new int[]{7});
 622     }
 623 
 624     @Test(expected = AssertionError.class)
 625     public void test60() {
 626         test("test12Snippet", 8, new int[]{8});
 627     }
 628 
 629     public static void test13Snippet(Object[] a, Object[] 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();
 672                 Assert.assertTrue(expectedBarriers.apply(graph) == barriers);
 673             }
 674             ResolvedJavaField barrierIndexField = getMetaAccess().lookupJavaField(WriteBarrierVerificationTest.class.getDeclaredField("barrierIndex"));
 675             LocationIdentity barrierIdentity = new FieldLocationIdentity(barrierIndexField);
 676             // Iterate over all write nodes and remove barriers according to input indices.
 677             NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
 678 
 679                 @Override
 680                 protected Boolean processNode(FixedNode node, Boolean currentState) {
 681                     if (node instanceof WriteNode) {
 682                         WriteNode write = (WriteNode) node;
 683                         LocationIdentity obj = write.getLocationIdentity();
 684                         if (obj.equals(barrierIdentity)) {
 685                             /*
 686                              * A "barrierIndex" variable was found and is checked against the input
 687                              * barrier array.
 688                              */
 689                             if (eliminateBarrier(write.value().asJavaConstant().asInt(), removedBarrierIndices)) {
 690                                 return true;
 691                             }
 692                         }
 693                     } else if (node instanceof SerialWriteBarrier || node instanceof G1PostWriteBarrier) {
 694                         // Remove flagged write barriers.
 695                         if (currentState) {
 696                             graph.removeFixed(((FixedWithNextNode) node));
 697                             return false;
 698                         }
 699                     }
 700                     return currentState;
 701                 }
 702 
 703                 private boolean eliminateBarrier(int index, int[] map) {
 704                     for (int i = 0; i < map.length; i++) {
 705                         if (map[i] == index) {
 706                             return true;
 707                         }
 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 }