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