1 /*
   2  * Copyright (c) 2018, Red Hat, Inc. 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  * common code to run and validate tests of code generation for
  26  * volatile ops on AArch64
  27  *
  28  * incoming args are <testclass> <testtype>
  29  *
  30  * where <testclass> in {TestVolatileLoad,
  31  *                       TestVolatileStore,
  32  *                       TestUnsafeVolatileLoad,
  33  *                       TestUnsafeVolatileStore,
  34  *                       TestUnsafeVolatileCAS,
  35  *                       TestUnsafeVolatileWeakCAS,
  36  *                       TestUnsafeVolatileCAE,
  37  *                       TestUnsafeVolatileGAS}
  38  * and <testtype> in {G1,
  39  *                    Serial,
  40  *                    Parallel,
  41  *                    Shenandoah,
  42  *                    ShenandoahIU}
  43  */
  44 
  45 
  46 package compiler.c2.aarch64;
  47 
  48 import java.util.List;
  49 import java.util.ListIterator;
  50 import java.util.Iterator;
  51 import java.util.regex.Pattern;
  52 import java.io.*;
  53 
  54 import jdk.test.lib.Asserts;
  55 import jdk.test.lib.compiler.InMemoryJavaCompiler;
  56 import jdk.test.lib.process.OutputAnalyzer;
  57 import jdk.test.lib.process.ProcessTools;
  58 import sun.hotspot.WhiteBox;
  59 
  60 // runner class that spawns a new JVM to exercises a combination of
  61 // volatile MemOp and GC. The ops are compiled with the dmb -->
  62 // ldar/stlr transforms either enabled or disabled. this runner parses
  63 // the PrintOptoAssembly output checking that the generated code is
  64 // correct.
  65 
  66 public class TestVolatiles {
  67     public void runtest(String classname, String testType) throws Throwable {
  68         // n.b. clients omit the package name for the class
  69         String fullclassname = "compiler.c2.aarch64." + classname;
  70         // build up a command line for the spawned JVM
  71         String[] procArgs;
  72         int argcount;
  73         // add one or two extra arguments according to test type
  74         // i.e. GC type plus GC conifg
  75         switch(testType) {
  76         case "G1":
  77             argcount = 9;
  78             procArgs = new String[argcount];
  79             procArgs[argcount - 2] = "-XX:+UseG1GC";
  80             break;
  81         case "Parallel":
  82             argcount = 9;
  83             procArgs = new String[argcount];
  84             procArgs[argcount - 2] = "-XX:+UseParallelGC";
  85             break;
  86         case "Serial":
  87             argcount = 9;
  88             procArgs = new String[argcount];
  89             procArgs[argcount - 2] = "-XX:+UseSerialGC";
  90             break;
  91         case "Shenandoah":
  92             argcount = 10;
  93             procArgs = new String[argcount];
  94             procArgs[argcount - 3] = "-XX:+UnlockExperimentalVMOptions";
  95             procArgs[argcount - 2] = "-XX:+UseShenandoahGC";
  96             break;
  97         case "ShenandoahIU":
  98             argcount = 11;
  99             procArgs = new String[argcount];
 100             procArgs[argcount - 4] = "-XX:+UnlockExperimentalVMOptions";
 101             procArgs[argcount - 3] = "-XX:+UseShenandoahGC";
 102             procArgs[argcount - 2] = "-XX:ShenandoahGCMode=iu";
 103             break;
 104         default:
 105             throw new RuntimeException("unexpected test type " + testType);
 106         }
 107 
 108         // fill in arguments common to all cases
 109 
 110         // the first round of test enables transform of barriers to
 111         // use acquiring loads and releasing stores by setting arg
 112         // zero appropriately. this arg is reset in the second run to
 113         // disable the transform.
 114 
 115         procArgs[0] = "-XX:-UseBarriersForVolatile";
 116         procArgs[1] = "-XX:+UseCompressedOops";
 117 
 118         procArgs[2] = "-XX:-TieredCompilation";
 119         procArgs[3] = "-XX:+PrintOptoAssembly";
 120         procArgs[4] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*";
 121         procArgs[5] = "--add-exports";
 122         procArgs[6] = "java.base/jdk.internal.misc=ALL-UNNAMED";
 123         procArgs[argcount - 1] = fullclassname;
 124 
 125         runtest(classname, testType, false, true, procArgs);
 126         // rerun the test class without the transform applied and
 127         // check the alternative generation is as expected
 128 
 129         procArgs[0] = "-XX:+UseBarriersForVolatile";
 130         runtest(classname, testType, true, true, procArgs);
 131 
 132         if (!classname.equals("TestUnsafeVolatileGAA")) {
 133             procArgs[0] = "-XX:-UseBarriersForVolatile";
 134             procArgs[1] = "-XX:-UseCompressedOops";
 135             runtest(classname, testType, false, false, procArgs);
 136 
 137             procArgs[0] = "-XX:+UseBarriersForVolatile";
 138             runtest(classname, testType, true, false, procArgs);
 139         }
 140     }
 141 
 142 
 143     public void runtest(String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops, String[] procArgs) throws Throwable {
 144         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs);
 145         OutputAnalyzer output = new OutputAnalyzer(pb.start());
 146 
 147         output.stderrShouldBeEmptyIgnoreVMWarnings();
 148         output.stdoutShouldNotBeEmpty();
 149         output.shouldHaveExitValue(0);
 150 
 151         // check the output for the correct asm sequence as
 152         // appropriate to test class, test type and whether transform
 153         // was applied
 154 
 155         checkoutput(output, classname, testType, useBarriersForVolatile, useCompressedOops);
 156     }
 157 
 158     // skip through output returning a line containing the desireed
 159     // substring or null
 160     private String skipTo(Iterator<String> iter, String substring)
 161     {
 162         while (iter.hasNext()) {
 163             String nextLine = iter.next();
 164             if (nextLine.matches(".*" + substring + ".*")) {
 165                 return nextLine;
 166             }
 167         }
 168         return null;
 169     }
 170 
 171     // locate the start of compiler output for the desired method and
 172     // then check that each expected instruction occurs in the output
 173     // in the order supplied. throw an excpetion if not found.
 174     // n.b. the spawned JVM's output is included in the exception
 175     // message to make it easeir to identify what is missing.
 176 
 177     private boolean checkCompile(Iterator<String> iter, String methodname, String[] expected, OutputAnalyzer output, boolean do_throw)
 178     {
 179         // trace call to allow eyeball check of what we are checking against
 180         System.out.println("checkCompile(" + methodname + ",");
 181         String sepr = "  { ";
 182         for (String s : expected) {
 183             System.out.print(sepr);
 184             System.out.print(s);
 185             sepr = ",\n    ";
 186         }
 187         System.out.println(" })");
 188 
 189         // look for the start of an opto assembly print block
 190         String match = skipTo(iter, Pattern.quote("{method}"));
 191         if (match == null) {
 192             if (do_throw) {
 193                 throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput());
 194             }
 195             return false;
 196         }
 197         // check the compiled method name is right
 198         match = skipTo(iter, Pattern.quote("- name:"));
 199         if (match == null) {
 200             if (do_throw) {
 201                 throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput());
 202             }
 203             return false;
 204         }
 205         if (!match.contains(methodname)) {
 206             if (do_throw) {
 207                 throw new RuntimeException("Wrong method " + match + "!\n  -- expecting " + methodname + "\n\n" + output.getOutput());
 208             }
 209             return false;
 210         }
 211         // make sure we can match each expected term in order
 212         for (String s : expected) {
 213             match = skipTo(iter, s);
 214             if (match == null) {
 215                 if (do_throw) {
 216                     throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput());
 217                 }
 218                 return false;
 219             }
 220         }
 221         return true;
 222     }
 223 
 224     // check for expected asm output from a volatile load
 225 
 226     private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 227     {
 228         Iterator<String> iter = output.asLines().listIterator();
 229 
 230         // we shoud see this same sequence for normal or unsafe volatile load
 231         // for both int and Object fields
 232 
 233         String[] matches;
 234 
 235         if (!useBarriersForVolatile) {
 236             matches = new String[] {
 237                 "ldarw",
 238                 "membar_acquire \\(elided\\)",
 239                 "ret"
 240             };
 241         } else {
 242             matches = new String[] {
 243                 "ldrw",
 244                 "membar_acquire",
 245                 "dmb ish",
 246                 "ret"
 247             };
 248         }
 249 
 250         checkCompile(iter, "testInt", matches, output, true);
 251 
 252         if (!useBarriersForVolatile) {
 253             matches = new String[] {
 254                 useCompressedOops ? "ldarw?" : "ldar",
 255                 "membar_acquire \\(elided\\)",
 256                 "ret"
 257             };
 258         } else {
 259             matches = new String[] {
 260                 useCompressedOops ? "ldrw?" : "ldr",
 261                 "membar_acquire",
 262                 "dmb ish",
 263                 "ret"
 264             };
 265         }
 266 
 267         checkCompile(iter, "testObj", matches, output, true);
 268 
 269     }
 270 
 271     // check for expected asm output from a volatile store
 272 
 273     private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 274     {
 275         Iterator<String> iter = output.asLines().listIterator();
 276 
 277         String[] matches;
 278 
 279         // non object stores are straightforward
 280         if (!useBarriersForVolatile) {
 281             // this is the sequence of instructions for all cases
 282             matches = new String[] {
 283                 "membar_release \\(elided\\)",
 284                 "stlrw",
 285                 "membar_volatile \\(elided\\)",
 286                 "ret"
 287             };
 288         } else {
 289             // this is the alternative sequence of instructions
 290             matches = new String[] {
 291                 "membar_release",
 292                 "dmb ish",
 293                 "strw",
 294                 "membar_volatile",
 295                 "dmb ish",
 296                 "ret"
 297             };
 298         }
 299 
 300         checkCompile(iter, "testInt", matches, output, true);
 301 
 302         // object stores will be as above except for when the GC
 303         // introduces barriers for card marking
 304 
 305         if (!useBarriersForVolatile) {
 306             switch (testType) {
 307             default:
 308                 // this is the basic sequence of instructions
 309                 matches = new String[] {
 310                     "membar_release \\(elided\\)",
 311                     useCompressedOops ? "stlrw?" : "stlr",
 312                     "membar_volatile \\(elided\\)",
 313                     "ret"
 314                 };
 315                 break;
 316             case "G1":
 317                 // a card mark volatile barrier should be generated
 318                 // before the card mark strb
 319                 //
 320                 // following the fix for 8225776 the G1 barrier is now
 321                 // scheduled out of line after the membar volatile and
 322                 // and subsequent return
 323                 matches = new String[] {
 324                     "membar_release \\(elided\\)",
 325                     useCompressedOops ? "stlrw?" : "stlr",
 326                     "membar_volatile \\(elided\\)",
 327                     "ret",
 328                     "membar_volatile",
 329                     "dmb ish",
 330                     "strb"
 331                 };
 332                 break;
 333             case "Shenandoah":
 334             case "ShenandoahIU":
 335                  // Shenandoah generates normal object graphs for
 336                  // volatile stores
 337                 matches = new String[] {
 338                     "membar_release \\(elided\\)",
 339                     useCompressedOops ? "stlrw?" : "stlr",
 340                     "membar_volatile \\(elided\\)",
 341                     "ret"
 342                 };
 343                 break;
 344             }
 345         } else {
 346             switch (testType) {
 347             default:
 348                 // this is the basic sequence of instructions
 349                 matches = new String[] {
 350                     "membar_release",
 351                     "dmb ish",
 352                     useCompressedOops ? "strw?" : "str",
 353                     "membar_volatile",
 354                     "dmb ish",
 355                     "ret"
 356                 };
 357                 break;
 358             case "G1":
 359                 // a card mark volatile barrier should be generated
 360                 // before the card mark strb
 361                 //
 362                 // following the fix for 8225776 the G1 barrier is now
 363                 // scheduled out of line after the membar volatile and
 364                 // and subsequent return
 365                 matches = new String[] {
 366                     "membar_release",
 367                     "dmb ish",
 368                     useCompressedOops ? "strw?" : "str",
 369                     "membar_volatile",
 370                     "dmb ish",
 371                     "ret",
 372                     "membar_volatile",
 373                     "dmb ish",
 374                     "strb"
 375                 };
 376                 break;
 377             case "CMSCondMark":
 378                 // a card mark volatile barrier should be generated
 379                 // before the card mark strb from the StoreCM and the
 380                 // storestore barrier from the StoreCM should be elided
 381                 matches = new String[] {
 382                     "membar_release",
 383                     "dmb ish",
 384                     useCompressedOops ? "strw?" : "str",
 385                     "membar_volatile",
 386                     "dmb ish",
 387                     "storestore \\(elided\\)",
 388                     "strb",
 389                     "membar_volatile",
 390                     "dmb ish",
 391                     "ret"
 392                 };
 393                 break;
 394             case "CMS":
 395                 // a volatile card mark membar should not be generated
 396                 // before the card mark strb from the StoreCM and the
 397                 // storestore barrier from the StoreCM should be generated
 398                 // as "dmb ishst"
 399                 matches = new String[] {
 400                     "membar_release",
 401                     "dmb ish",
 402                     useCompressedOops ? "strw?" : "str",
 403                     "storestore",
 404                     "dmb ishst",
 405                     "strb",
 406                     "membar_volatile",
 407                     "dmb ish",
 408                     "ret"
 409                 };
 410                 break;
 411 
 412             case "Shenandoah":
 413             case "ShenandoahIU":
 414                  // Shenandoah generates normal object graphs for
 415                  // volatile stores
 416                 matches = new String[] {
 417                     "membar_release",
 418                     "dmb ish",
 419                     useCompressedOops ? "strw?" : "str",
 420                     "membar_volatile",
 421                     "dmb ish",
 422                     "ret"
 423                 };
 424                 break;
 425             }
 426         }
 427 
 428         checkCompile(iter, "testObj", matches, output, true);
 429     }
 430 
 431     // check for expected asm output from a volatile cas
 432 
 433     private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 434     {
 435         Iterator<String> iter = output.asLines().listIterator();
 436 
 437         String[] matches;
 438         String[][] tests = {
 439             { "testInt", "cmpxchgw" },
 440             { "testLong", "cmpxchg" },
 441             { "testByte", "cmpxchgb" },
 442             { "testShort", "cmpxchgs" },
 443         };
 444 
 445         for (String[] test : tests) {
 446             // non object stores are straightforward
 447             if (!useBarriersForVolatile) {
 448                 // this is the sequence of instructions for all cases
 449                 matches = new String[] {
 450                     "membar_release \\(elided\\)",
 451                     test[1] + "_acq",
 452                     "membar_acquire \\(elided\\)",
 453                     "ret"
 454                 };
 455             } else {
 456                 // this is the alternative sequence of instructions
 457                 matches = new String[] {
 458                     "membar_release",
 459                     "dmb ish",
 460                     test[1] + " ",
 461                     "membar_acquire",
 462                     "dmb ish",
 463                     "ret"
 464                 };
 465             }
 466 
 467             checkCompile(iter, test[0], matches, output, true);
 468         }
 469 
 470         // object stores will be as above except for when the GC
 471         // introduces barriers for card marking
 472 
 473         if (!useBarriersForVolatile) {
 474             switch (testType) {
 475             default:
 476                 // this is the basic sequence of instructions
 477                 matches = new String[] {
 478                     "membar_release \\(elided\\)",
 479                     useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
 480                     "strb",
 481                     "membar_acquire \\(elided\\)",
 482                     "ret"
 483                 };
 484                 break;
 485             case "G1":
 486                 // a card mark volatile barrier should be generated
 487                 // before the card mark strb
 488                 //
 489                 // following the fix for 8225776 the G1 barrier is now
 490                 // scheduled out of line after the membar acquire and
 491                 // and subsequent return
 492                 matches = new String[] {
 493                     "membar_release \\(elided\\)",
 494                     useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
 495                     "membar_acquire \\(elided\\)",
 496                     "ret",
 497                     "membar_volatile",
 498                     "dmb ish",
 499                     "strb"
 500                 };
 501                 break;
 502             case "Shenandoah":
 503             case "ShenandoahIU":
 504                 // For volatile CAS, Shenanodoah generates normal
 505                 // graphs with a shenandoah-specific cmpxchg
 506                 matches = new String[] {
 507                     "membar_release \\(elided\\)",
 508                     useCompressedOops ? "cmpxchgw?_acq_shenandoah" : "cmpxchg_acq_shenandoah",
 509                     "membar_acquire \\(elided\\)",
 510                     "ret"
 511                 };
 512                 break;
 513             }
 514         } else {
 515             switch (testType) {
 516             default:
 517                 // this is the basic sequence of instructions
 518                 matches = new String[] {
 519                     "membar_release",
 520                     "dmb ish",
 521                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 522                     "membar_acquire",
 523                     "dmb ish",
 524                     "ret"
 525                 };
 526                 break;
 527             case "G1":
 528                 // a card mark volatile barrier should be generated
 529                 // before the card mark strb
 530                 //
 531                 // following the fix for 8225776 the G1 barrier is now
 532                 // scheduled out of line after the membar acquire and
 533                 // and subsequent return
 534                 matches = new String[] {
 535                     "membar_release",
 536                     "dmb ish",
 537                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 538                     "membar_acquire",
 539                     "dmb ish",
 540                     "ret",
 541                     "membar_volatile",
 542                     "dmb ish",
 543                     "strb"
 544                 };
 545                 break;
 546             case "CMSCondMark":
 547                 // a card mark volatile barrier should be generated
 548                 // before the card mark strb from the StoreCM and the
 549                 // storestore barrier from the StoreCM should be elided
 550                 matches = new String[] {
 551                     "membar_release",
 552                     "dmb ish",
 553                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 554                     "membar_volatile",
 555                     "dmb ish",
 556                     "storestore \\(elided\\)",
 557                     "strb",
 558                     "membar_acquire",
 559                     "dmb ish",
 560                     "ret"
 561                 };
 562                 break;
 563             case "CMS":
 564                 // a volatile card mark membar should not be generated
 565                 // before the card mark strb from the StoreCM and the
 566                 // storestore barrier from the StoreCM should be generated
 567                 // as "dmb ishst"
 568                 matches = new String[] {
 569                     "membar_release",
 570                     "dmb ish",
 571                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 572                     "storestore",
 573                     "dmb ishst",
 574                     "strb",
 575                     "membar_acquire",
 576                     "dmb ish",
 577                     "ret"
 578                 };
 579                 break;
 580             case "Shenandoah":
 581             case "ShenandoahIU":
 582                 // For volatile CAS, Shenanodoah generates normal
 583                 // graphs with a shenandoah-specific cmpxchg
 584                 matches = new String[] {
 585                     "membar_release",
 586                     "dmb ish",
 587                     useCompressedOops ? "cmpxchgw?_shenandoah" : "cmpxchg_shenandoah",
 588                     "membar_acquire",
 589                     "dmb ish",
 590                     "ret"
 591                 };
 592                 break;
 593             }
 594         }
 595 
 596         checkCompile(iter, "testObj", matches, output, true);
 597     }
 598 
 599     private void checkcae(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 600     {
 601         ListIterator<String> iter = output.asLines().listIterator();
 602 
 603         String[] matches;
 604         String[][] tests = {
 605             { "testInt", "cmpxchgw" },
 606             { "testLong", "cmpxchg" },
 607             { "testByte", "cmpxchgb" },
 608             { "testShort", "cmpxchgs" },
 609         };
 610 
 611         for (String[] test : tests) {
 612             // non object stores are straightforward
 613             if (!useBarriersForVolatile) {
 614                 // this is the sequence of instructions for all cases
 615                 matches = new String[] {
 616                     "membar_release \\(elided\\)",
 617                     test[1] + "_acq",
 618                     "membar_acquire \\(elided\\)",
 619                     "ret"
 620                 };
 621             } else {
 622                 // this is the alternative sequence of instructions
 623                 matches = new String[] {
 624                     "membar_release",
 625                     "dmb ish",
 626                     test[1] + " ",
 627                     "membar_acquire",
 628                     "dmb ish",
 629                     "ret"
 630                 };
 631             }
 632 
 633             checkCompile(iter, test[0], matches, output, true);
 634         }
 635 
 636         // object stores will be as above except for when the GC
 637         // introduces barriers for card marking
 638 
 639         if (!useBarriersForVolatile) {
 640             switch (testType) {
 641             default:
 642                 // this is the basic sequence of instructions
 643                 matches = new String[] {
 644                     "membar_release \\(elided\\)",
 645                     "strb",
 646                     useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
 647                     "membar_acquire \\(elided\\)",
 648                     "ret"
 649                 };
 650 
 651                 // card marking store may be scheduled before or after
 652                 // the cmpxchg so try both sequences.
 653                 int idx = iter.nextIndex();
 654                 if (!checkCompile(iter, "testObj", matches, output, false)) {
 655                     iter = output.asLines().listIterator(idx);
 656 
 657                     matches = new String[] {
 658                         "membar_release \\(elided\\)",
 659                         useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
 660                         "strb",
 661                         "membar_acquire \\(elided\\)",
 662                         "ret"
 663                     };
 664 
 665                     checkCompile(iter, "testObj", matches, output, true);
 666                 }
 667                 return;
 668 
 669             case "G1":
 670                 // a card mark volatile barrier should be generated
 671                 // before the card mark strb
 672                 //
 673                 // following the fix for 8225776 the G1 barrier is now
 674                 // scheduled out of line after the membar acquire and
 675                 // and subsequent return
 676                 matches = new String[] {
 677                     "membar_release \\(elided\\)",
 678                     useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq",
 679                     "membar_acquire \\(elided\\)",
 680                     "ret",
 681                     "membar_volatile",
 682                     "dmb ish",
 683                     "strb"
 684                 };
 685                 break;
 686             case "Shenandoah":
 687             case "ShenandoahIU":
 688                 // For volatile CAS, Shenanodoah generates normal
 689                 // graphs with a shenandoah-specific cmpxchg
 690                 matches = new String[] {
 691                     "membar_release \\(elided\\)",
 692                     useCompressedOops ? "cmpxchgw?_acq_shenandoah" : "cmpxchg_acq_shenandoah",
 693                     "membar_acquire \\(elided\\)",
 694                     "ret"
 695                 };
 696                 break;
 697             }
 698         } else {
 699             switch (testType) {
 700             default:
 701                 // this is the basic sequence of instructions
 702                 matches = new String[] {
 703                     "membar_release",
 704                     "dmb ish",
 705                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 706                     "membar_acquire",
 707                     "dmb ish",
 708                     "ret"
 709                 };
 710                 break;
 711             case "G1":
 712                 // a card mark volatile barrier should be generated
 713                 // before the card mark strb
 714                 //
 715                 // following the fix for 8225776 the G1 barrier is now
 716                 // scheduled out of line after the membar acquire and
 717                 // and subsequent return
 718                 matches = new String[] {
 719                     "membar_release",
 720                     "dmb ish",
 721                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 722                     "membar_acquire",
 723                     "dmb ish",
 724                     "ret",
 725                     "membar_volatile",
 726                     "dmb ish",
 727                     "strb"
 728                 };
 729                 break;
 730             case "CMSCondMark":
 731                 // a card mark volatile barrier should be generated
 732                 // before the card mark strb from the StoreCM and the
 733                 // storestore barrier from the StoreCM should be elided
 734                 matches = new String[] {
 735                     "membar_release",
 736                     "dmb ish",
 737                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 738                     "membar_volatile",
 739                     "dmb ish",
 740                     "storestore \\(elided\\)",
 741                     "strb",
 742                     "membar_acquire",
 743                     "dmb ish",
 744                     "ret"
 745                 };
 746                 break;
 747             case "CMS":
 748                 // a volatile card mark membar should not be generated
 749                 // before the card mark strb from the StoreCM and the
 750                 // storestore barrier from the StoreCM should be generated
 751                 // as "dmb ishst"
 752                 matches = new String[] {
 753                     "membar_release",
 754                     "dmb ish",
 755                     useCompressedOops ? "cmpxchgw? " : "cmpxchg ",
 756                     "storestore",
 757                     "dmb ishst",
 758                     "strb",
 759                     "membar_acquire",
 760                     "dmb ish",
 761                     "ret"
 762                 };
 763                 break;
 764             case "Shenandoah":
 765             case "ShenandoahIU":
 766                 // For volatile CAS, Shenanodoah generates normal
 767                 // graphs with a shenandoah-specific cmpxchg
 768                 matches = new String[] {
 769                     "membar_release",
 770                     "dmb ish",
 771                     useCompressedOops ? "cmpxchgw?_shenandoah" : "cmpxchg_shenandoah",
 772                     "membar_acquire",
 773                     "dmb ish",
 774                     "ret"
 775                 };
 776                 break;
 777             }
 778         }
 779 
 780         checkCompile(iter, "testObj", matches, output, true);
 781     }
 782 
 783     private void checkgas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 784     {
 785         Iterator<String> iter = output.asLines().listIterator();
 786 
 787         String[] matches;
 788         String[][] tests = {
 789             { "testInt", "atomic_xchgw" },
 790             { "testLong", "atomic_xchg" },
 791         };
 792 
 793         for (String[] test : tests) {
 794             // non object stores are straightforward
 795             if (!useBarriersForVolatile) {
 796                 // this is the sequence of instructions for all cases
 797                 matches = new String[] {
 798                     "membar_release \\(elided\\)",
 799                     test[1] + "_acq",
 800                     "membar_acquire \\(elided\\)",
 801                     "ret"
 802                 };
 803             } else {
 804                 // this is the alternative sequence of instructions
 805                 matches = new String[] {
 806                     "membar_release",
 807                     "dmb ish",
 808                     test[1] + " ",
 809                     "membar_acquire",
 810                     "dmb ish",
 811                     "ret"
 812                 };
 813             }
 814 
 815             checkCompile(iter, test[0], matches, output, true);
 816         }
 817 
 818         // object stores will be as above except for when the GC
 819         // introduces barriers for card marking
 820 
 821         if (!useBarriersForVolatile) {
 822             switch (testType) {
 823             default:
 824                 // this is the basic sequence of instructions
 825                 matches = new String[] {
 826                     "membar_release \\(elided\\)",
 827                     useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
 828                     "strb",
 829                     "membar_acquire \\(elided\\)",
 830                     "ret"
 831                 };
 832                 break;
 833             case "G1":
 834                 // a card mark volatile barrier should be generated
 835                 // before the card mark strb
 836                 //
 837                 // following the fix for 8225776 the G1 barrier is now
 838                 // scheduled out of line after the membar acquire and
 839                 // and subsequent return
 840                 matches = new String[] {
 841                     "membar_release \\(elided\\)",
 842                     useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
 843                     "membar_acquire \\(elided\\)",
 844                     "ret",
 845                     "membar_volatile",
 846                     "dmb ish",
 847                     "strb"
 848                 };
 849                 break;
 850             case "Shenandoah":
 851             case "ShenandoahIU":
 852                 matches = new String[] {
 853                     "membar_release \\(elided\\)",
 854                     useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq",
 855                     "membar_acquire \\(elided\\)",
 856                     "ret"
 857                 };
 858                 break;
 859             }
 860         } else {
 861             switch (testType) {
 862             default:
 863                 // this is the basic sequence of instructions
 864                 matches = new String[] {
 865                     "membar_release",
 866                     "dmb ish",
 867                     useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
 868                     "membar_acquire",
 869                     "dmb ish",
 870                     "ret"
 871                 };
 872                 break;
 873             case "G1":
 874                 // a card mark volatile barrier should be generated
 875                 // before the card mark strb
 876                 //
 877                 // following the fix for 8225776 the G1 barrier is now
 878                 // scheduled out of line after the membar acquire and
 879                 // and subsequent return
 880                 matches = new String[] {
 881                     "membar_release",
 882                     "dmb ish",
 883                     useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
 884                     "membar_acquire",
 885                     "dmb ish",
 886                     "ret",
 887                     "membar_volatile",
 888                     "dmb ish",
 889                     "strb"
 890                 };
 891                 break;
 892             case "CMSCondMark":
 893                 // a card mark volatile barrier should be generated
 894                 // before the card mark strb from the StoreCM and the
 895                 // storestore barrier from the StoreCM should be elided
 896                 matches = new String[] {
 897                     "membar_release",
 898                     "dmb ish",
 899                     useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
 900                     "membar_volatile",
 901                     "dmb ish",
 902                     "storestore \\(elided\\)",
 903                     "strb",
 904                     "membar_acquire",
 905                     "dmb ish",
 906                     "ret"
 907                 };
 908                 break;
 909             case "CMS":
 910                 // a volatile card mark membar should not be generated
 911                 // before the card mark strb from the StoreCM and the
 912                 // storestore barrier from the StoreCM should be generated
 913                 // as "dmb ishst"
 914                 matches = new String[] {
 915                     "membar_release",
 916                     "dmb ish",
 917                     useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
 918                     "storestore",
 919                     "dmb ishst",
 920                     "strb",
 921                     "membar_acquire",
 922                     "dmb ish",
 923                     "ret"
 924                 };
 925                 break;
 926             case "Shenandoah":
 927             case "ShenandoahIU":
 928                 matches = new String[] {
 929                     "membar_release",
 930                     "dmb ish",
 931                     useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ",
 932                     "membar_acquire",
 933                     "dmb ish",
 934                     "ret"
 935                 };
 936                 break;
 937             }
 938         }
 939 
 940         checkCompile(iter, "testObj", matches, output, true);
 941     }
 942 
 943     private void checkgaa(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
 944     {
 945         Iterator<String> iter = output.asLines().listIterator();
 946 
 947         String[] matches;
 948         String[][] tests = {
 949             { "testInt", "get_and_addI" },
 950             { "testLong", "get_and_addL" },
 951         };
 952 
 953         for (String[] test : tests) {
 954             // non object stores are straightforward
 955             if (!useBarriersForVolatile) {
 956                 // this is the sequence of instructions for all cases
 957                 matches = new String[] {
 958                     "membar_release \\(elided\\)",
 959                     test[1] + "_acq",
 960                     "membar_acquire \\(elided\\)",
 961                     "ret"
 962                 };
 963             } else {
 964                 // this is the alternative sequence of instructions
 965                 matches = new String[] {
 966                     "membar_release",
 967                     "dmb ish",
 968                     test[1] + " ",
 969                     "membar_acquire",
 970                     "dmb ish",
 971                     "ret"
 972                 };
 973             }
 974 
 975             checkCompile(iter, test[0], matches, output, true);
 976         }
 977 
 978     }
 979 
 980     // perform a check appropriate to the classname
 981 
 982     private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable
 983     {
 984         // trace call to allow eyeball check of what is being checked
 985         System.out.println("checkoutput(" +
 986                            classname + ", " +
 987                            testType + ", " +
 988                            useBarriersForVolatile + ")\n" +
 989                            output.getOutput());
 990 
 991         switch (classname) {
 992         case "TestVolatileLoad":
 993             checkload(output, testType, useBarriersForVolatile, useCompressedOops);
 994             break;
 995         case "TestVolatileStore":
 996             checkstore(output, testType, useBarriersForVolatile, useCompressedOops);
 997             break;
 998         case "TestUnsafeVolatileLoad":
 999             checkload(output, testType, useBarriersForVolatile, useCompressedOops);
1000             break;
1001         case "TestUnsafeVolatileStore":
1002             checkstore(output, testType, useBarriersForVolatile, useCompressedOops);
1003             break;
1004         case "TestUnsafeVolatileCAS":
1005         case "TestUnsafeVolatileWeakCAS":
1006             checkcas(output, testType, useBarriersForVolatile, useCompressedOops);
1007             break;
1008         case "TestUnsafeVolatileCAE":
1009             checkcae(output, testType, useBarriersForVolatile, useCompressedOops);
1010             break;
1011         case "TestUnsafeVolatileGAS":
1012             checkgas(output, testType, useBarriersForVolatile, useCompressedOops);
1013             break;
1014         case "TestUnsafeVolatileGAA":
1015             checkgaa(output, testType, useBarriersForVolatile);
1016             break;
1017         }
1018     }
1019 }