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