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