test/hotspot/jtreg/compiler/c2/aarch64/TestVolatiles.java
changeset 50874 551c340ca01a
child 51008 8df91a1b549b
equal deleted inserted replaced
50873:ce53844224b6 50874:551c340ca01a
       
     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  * and <testtype> in {G1,
       
    36  *                    CMS,
       
    37  *                    CMSCondCardMark,
       
    38  *                    Serial,
       
    39  *                    Parallel}
       
    40  */
       
    41 
       
    42 
       
    43 package compiler.c2.aarch64;
       
    44 
       
    45 import java.util.List;
       
    46 import java.util.Iterator;
       
    47 import java.io.*;
       
    48 
       
    49 import jdk.test.lib.Asserts;
       
    50 import jdk.test.lib.compiler.InMemoryJavaCompiler;
       
    51 import jdk.test.lib.process.OutputAnalyzer;
       
    52 import jdk.test.lib.process.ProcessTools;
       
    53 
       
    54 // runner class that spawns a new JVM to exercises a combination of
       
    55 // volatile MemOp and GC. The ops are compiled with the dmb -->
       
    56 // ldar/stlr transforms either enabled or disabled. this runner parses
       
    57 // the PrintOptoAssembly output checking that the generated code is
       
    58 // correct.
       
    59 
       
    60 public class TestVolatiles {
       
    61     public void runtest(String classname, String testType) throws Throwable {
       
    62         // n.b. clients omit the package name for the class
       
    63         String fullclassname = "compiler.c2.aarch64." + classname;
       
    64         // build up a command line for the spawned JVM
       
    65         String[] procArgs;
       
    66         int argcount;
       
    67         // add one or two extra arguments according to test type
       
    68         // i.e. GC type plus GC conifg
       
    69         switch(testType) {
       
    70         case "G1":
       
    71             argcount = 8;
       
    72             procArgs = new String[argcount];
       
    73             procArgs[argcount - 2] = "-XX:+UseG1GC";
       
    74             break;
       
    75         case "Parallel":
       
    76             argcount = 8;
       
    77             procArgs = new String[argcount];
       
    78             procArgs[argcount - 2] = "-XX:+UseParallelGC";
       
    79             break;
       
    80         case "Serial":
       
    81             argcount = 8;
       
    82             procArgs = new String[argcount];
       
    83             procArgs[argcount - 2] = "-XX:+UseSerialGC";
       
    84             break;
       
    85         case "CMS":
       
    86             argcount = 9 ;
       
    87             procArgs = new String[argcount];
       
    88             procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC";
       
    89             procArgs[argcount - 2] = "-XX:-UseCondCardMark";
       
    90             break;
       
    91         case "CMSCondMark":
       
    92             argcount = 9 ;
       
    93             procArgs = new String[argcount];
       
    94             procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC";
       
    95             procArgs[argcount - 2] = "-XX:+UseCondCardMark";
       
    96             break;
       
    97         default:
       
    98             throw new RuntimeException("unexpected test type " + testType);
       
    99         }
       
   100 
       
   101         // fill in arguments common to all cases
       
   102 
       
   103         // the first round of test enables transform of barriers to
       
   104         // use acquiring loads and releasing stores by setting arg
       
   105         // zero appropriately. this arg is reset in the second run to
       
   106         // disable the transform.
       
   107 
       
   108         procArgs[0] = "-XX:-UseBarriersForVolatile";
       
   109 
       
   110         procArgs[1] = "-XX:-TieredCompilation";
       
   111         procArgs[2] = "-XX:+PrintOptoAssembly";
       
   112         procArgs[3] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*";
       
   113         procArgs[4] = "--add-exports";
       
   114         procArgs[5] = "java.base/jdk.internal.misc=ALL-UNNAMED";
       
   115         procArgs[argcount - 1] = fullclassname;
       
   116 
       
   117         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs);
       
   118         OutputAnalyzer output = new OutputAnalyzer(pb.start());
       
   119 
       
   120         output.stderrShouldBeEmptyIgnoreVMWarnings();
       
   121         output.stdoutShouldNotBeEmpty();
       
   122         output.shouldHaveExitValue(0);
       
   123 
       
   124         // check the output for the correct asm sequence as
       
   125         // appropriate to test class, test type and whether transform
       
   126         // was applied
       
   127 
       
   128         checkoutput(output, classname, testType, false);
       
   129 
       
   130         // rerun the test class without the transform applied and
       
   131         // check the alternative generation is as expected
       
   132 
       
   133         procArgs[0] = "-XX:+UseBarriersForVolatile";
       
   134 
       
   135         pb = ProcessTools.createJavaProcessBuilder(procArgs);
       
   136         output = new OutputAnalyzer(pb.start());
       
   137 
       
   138         output.stderrShouldBeEmptyIgnoreVMWarnings();
       
   139         output.stdoutShouldNotBeEmpty();
       
   140         output.shouldHaveExitValue(0);
       
   141 
       
   142         // again check the output for the correct asm sequence
       
   143 
       
   144         checkoutput(output, classname, testType, true);
       
   145     }
       
   146 
       
   147     // skip through output returning a line containing the desireed
       
   148     // substring or null
       
   149     private String skipTo(Iterator<String> iter, String substring)
       
   150     {
       
   151         while (iter.hasNext()) {
       
   152             String nextLine = iter.next();
       
   153             if (nextLine.contains(substring)) {
       
   154                 return nextLine;
       
   155             }
       
   156         }
       
   157         return null;
       
   158     }
       
   159 
       
   160     // locate the start of compiler output for the desired method and
       
   161     // then check that each expected instruction occurs in the output
       
   162     // in the order supplied. throw an excpetion if not found.
       
   163     // n.b. the spawned JVM's output is included in the exception
       
   164     // message to make it easeir to identify what is missing.
       
   165 
       
   166     private void checkCompile(Iterator<String> iter, String methodname, String[] expected, OutputAnalyzer output)
       
   167     {
       
   168         // trace call to allow eyeball check of what we are checking against
       
   169         System.out.println("checkCompile(" + methodname + ",");
       
   170         String sepr = "  { ";
       
   171         for (String s : expected) {
       
   172             System.out.print(sepr);
       
   173             System.out.print(s);
       
   174             sepr = ",\n    ";
       
   175         }
       
   176         System.out.println(" })");
       
   177 
       
   178         // look for the start of an opto assembly print block
       
   179         String match = skipTo(iter, "{method}");
       
   180         if (match == null) {
       
   181             throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput());
       
   182         }
       
   183         // check the compiled method name is right
       
   184         match = skipTo(iter, "- name:");
       
   185         if (match == null) {
       
   186             throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput());
       
   187         }
       
   188         if (!match.contains(methodname)) {
       
   189             throw new RuntimeException("Wrong method " + match + "!\n  -- expecting " + methodname + "\n\n" + output.getOutput());
       
   190         }
       
   191         // make sure we can match each expected term in order
       
   192         for (String s : expected) {
       
   193             match = skipTo(iter, s);
       
   194             if (match == null) {
       
   195                 throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput());
       
   196             }
       
   197         }
       
   198     }
       
   199 
       
   200     // check for expected asm output from a volatile load
       
   201 
       
   202     private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
       
   203     {
       
   204         Iterator<String> iter = output.asLines().listIterator();
       
   205 
       
   206         // we shoud see this same sequence for normal or unsafe volatile load
       
   207         // for both int and Object fields
       
   208 
       
   209         String[] matches;
       
   210 
       
   211         if (!useBarriersForVolatile) {
       
   212             matches = new String[] {
       
   213                 "ldarw",
       
   214                 "membar_acquire (elided)",
       
   215                 "ret"
       
   216             };
       
   217         } else {
       
   218             matches = new String[] {
       
   219                 "ldrw",
       
   220                 "membar_acquire",
       
   221                 "dmb ish",
       
   222                 "ret"
       
   223             };
       
   224         }
       
   225 
       
   226         checkCompile(iter, "testInt", matches, output);
       
   227 
       
   228         checkCompile(iter, "testObj", matches, output) ;
       
   229 
       
   230     }
       
   231 
       
   232     // check for expected asm output from a volatile store
       
   233 
       
   234     private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
       
   235     {
       
   236         Iterator<String> iter = output.asLines().listIterator();
       
   237 
       
   238         String[] matches;
       
   239 
       
   240         // non object stores are straightforward
       
   241         if (!useBarriersForVolatile) {
       
   242             // this is the sequence of instructions for all cases
       
   243             matches = new String[] {
       
   244                 "membar_release (elided)",
       
   245                 "stlrw",
       
   246                 "membar_volatile (elided)",
       
   247                 "ret"
       
   248             };
       
   249         } else {
       
   250             // this is the alternative sequence of instructions
       
   251             matches = new String[] {
       
   252                 "membar_release",
       
   253                 "dmb ish",
       
   254                 "strw",
       
   255                 "membar_volatile",
       
   256                 "dmb ish",
       
   257                 "ret"
       
   258             };
       
   259         }
       
   260 
       
   261         checkCompile(iter, "testInt", matches, output);
       
   262 
       
   263         // object stores will be as above except for when the GC
       
   264         // introduces barriers for card marking
       
   265 
       
   266         if (!useBarriersForVolatile) {
       
   267             switch (testType) {
       
   268             default:
       
   269                 // this is the basic sequence of instructions
       
   270                 matches = new String[] {
       
   271                     "membar_release (elided)",
       
   272                     "stlrw",
       
   273                     "membar_volatile (elided)",
       
   274                     "ret"
       
   275                 };
       
   276                 break;
       
   277             case "G1":
       
   278                 // a card mark volatile barrier should be generated
       
   279                 // before the card mark strb
       
   280                 matches = new String[] {
       
   281                     "membar_release (elided)",
       
   282                     "stlrw",
       
   283                     "membar_volatile",
       
   284                     "dmb ish",
       
   285                     "strb",
       
   286                     "membar_volatile (elided)",
       
   287                     "ret"
       
   288                 };
       
   289                 break;
       
   290             case "CMSCondCardMark":
       
   291                 // a card mark volatile barrier should be generated
       
   292                 // before the card mark strb from the StoreCM and the
       
   293                 // storestore barrier from the StoreCM should be elided
       
   294                 matches = new String[] {
       
   295                     "membar_release (elided)",
       
   296                     "stlrw",
       
   297                     "membar_volatile",
       
   298                     "dmb ish",
       
   299                     "storestore (elided)",
       
   300                     "strb",
       
   301                     "membar_volatile (elided)",
       
   302                     "ret"
       
   303                 };
       
   304                 break;
       
   305             case "CMS":
       
   306                 // a volatile card mark membar should not be generated
       
   307                 // before the card mark strb from the StoreCM and the
       
   308                 // storestore barrier from the StoreCM should be elided
       
   309                 matches = new String[] {
       
   310                     "membar_release (elided)",
       
   311                     "stlrw",
       
   312                     "storestore (elided)",
       
   313                     "strb",
       
   314                     "membar_volatile (elided)",
       
   315                     "ret"
       
   316                 };
       
   317                 break;
       
   318             }
       
   319         } else {
       
   320             switch (testType) {
       
   321             default:
       
   322                 // this is the basic sequence of instructions
       
   323                 matches = new String[] {
       
   324                     "membar_release",
       
   325                     "dmb ish",
       
   326                     "strw",
       
   327                     "membar_volatile",
       
   328                     "dmb ish",
       
   329                     "ret"
       
   330                 };
       
   331                 break;
       
   332             case "G1":
       
   333                 // a card mark volatile barrier should be generated
       
   334                 // before the card mark strb
       
   335                 matches = new String[] {
       
   336                     "membar_release",
       
   337                     "dmb ish",
       
   338                     "strw",
       
   339                     "membar_volatile",
       
   340                     "dmb ish",
       
   341                     "strb",
       
   342                     "membar_volatile",
       
   343                     "dmb ish",
       
   344                     "ret"
       
   345                 };
       
   346                 break;
       
   347             case "CMSCondCardMark":
       
   348                 // a card mark volatile barrier should be generated
       
   349                 // before the card mark strb from the StoreCM and the
       
   350                 // storestore barrier from the StoreCM should be elided
       
   351                 matches = new String[] {
       
   352                     "membar_release",
       
   353                     "dmb ish",
       
   354                     "strw",
       
   355                     "membar_volatile",
       
   356                     "dmb ish",
       
   357                     "storestore (elided)",
       
   358                     "strb",
       
   359                     "membar_volatile",
       
   360                     "dmb ish",
       
   361                     "ret"
       
   362                 };
       
   363                 break;
       
   364             case "CMS":
       
   365                 // a volatile card mark membar should not be generated
       
   366                 // before the card mark strb from the StoreCM and the
       
   367                 // storestore barrier from the StoreCM should be generated
       
   368                 // as "dmb ishst"
       
   369                 matches = new String[] {
       
   370                     "membar_release",
       
   371                     "dmb ish",
       
   372                     "strw",
       
   373                     "storestore",
       
   374                     "dmb ishst",
       
   375                     "strb",
       
   376                     "membar_volatile",
       
   377                     "dmb ish",
       
   378                     "ret"
       
   379                 };
       
   380                 break;
       
   381             }
       
   382         }
       
   383 
       
   384         checkCompile(iter, "testObj", matches, output);
       
   385     }
       
   386 
       
   387     // check for expected asm output from a volatile cas
       
   388 
       
   389     private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable
       
   390     {
       
   391         Iterator<String> iter = output.asLines().listIterator();
       
   392 
       
   393         String[] matches;
       
   394 
       
   395         // non object stores are straightforward
       
   396         if (!useBarriersForVolatile) {
       
   397             // this is the sequence of instructions for all cases
       
   398             matches = new String[] {
       
   399                 "membar_release (elided)",
       
   400                 "cmpxchgw_acq",
       
   401                 "membar_acquire (elided)",
       
   402                 "ret"
       
   403             };
       
   404         } else {
       
   405             // this is the alternative sequence of instructions
       
   406             matches = new String[] {
       
   407                 "membar_release",
       
   408                 "dmb ish",
       
   409                 "cmpxchgw",
       
   410                 "membar_acquire",
       
   411                 "dmb ish",
       
   412                 "ret"
       
   413             };
       
   414         }
       
   415 
       
   416         checkCompile(iter, "testInt", matches, output);
       
   417 
       
   418         // object stores will be as above except for when the GC
       
   419         // introduces barriers for card marking
       
   420 
       
   421         if (!useBarriersForVolatile) {
       
   422             switch (testType) {
       
   423             default:
       
   424                 // this is the basic sequence of instructions
       
   425                 matches = new String[] {
       
   426                     "membar_release (elided)",
       
   427                     "cmpxchgw_acq",
       
   428                     "strb",
       
   429                     "membar_acquire (elided)",
       
   430                     "ret"
       
   431                 };
       
   432                 break;
       
   433             case "G1":
       
   434                 // a card mark volatile barrier should be generated
       
   435                 // before the card mark strb
       
   436                 matches = new String[] {
       
   437                     "membar_release (elided)",
       
   438                     "cmpxchgw_acq",
       
   439                     "membar_volatile",
       
   440                     "dmb ish",
       
   441                     "strb",
       
   442                     "membar_acquire (elided)",
       
   443                     "ret"
       
   444                 };
       
   445                 break;
       
   446             case "CMSCondCardMark":
       
   447                 // a card mark volatile barrier should be generated
       
   448                 // before the card mark strb from the StoreCM and the
       
   449                 // storestore barrier from the StoreCM should be elided
       
   450                 matches = new String[] {
       
   451                     "membar_release (elided)",
       
   452                     "cmpxchgw_acq",
       
   453                     "membar_volatile",
       
   454                     "dmb ish",
       
   455                     "storestore (elided)",
       
   456                     "strb",
       
   457                     "membar_acquire (elided)",
       
   458                     "ret"
       
   459                 };
       
   460                 break;
       
   461             case "CMS":
       
   462                 // a volatile card mark membar should not be generated
       
   463                 // before the card mark strb from the StoreCM and the
       
   464                 // storestore barrier from the StoreCM should be elided
       
   465                 matches = new String[] {
       
   466                     "membar_release (elided)",
       
   467                     "cmpxchgw_acq",
       
   468                     "storestore (elided)",
       
   469                     "strb",
       
   470                     "membar_acquire (elided)",
       
   471                     "ret"
       
   472                 };
       
   473                 break;
       
   474             }
       
   475         } else {
       
   476             switch (testType) {
       
   477             default:
       
   478                 // this is the basic sequence of instructions
       
   479                 matches = new String[] {
       
   480                     "membar_release",
       
   481                     "dmb ish",
       
   482                     "cmpxchgw",
       
   483                     "membar_acquire",
       
   484                     "dmb ish",
       
   485                     "ret"
       
   486                 };
       
   487                 break;
       
   488             case "G1":
       
   489                 // a card mark volatile barrier should be generated
       
   490                 // before the card mark strb
       
   491                 matches = new String[] {
       
   492                     "membar_release",
       
   493                     "dmb ish",
       
   494                     "cmpxchgw",
       
   495                     "membar_volatile",
       
   496                     "dmb ish",
       
   497                     "strb",
       
   498                     "membar_acquire",
       
   499                     "dmb ish",
       
   500                     "ret"
       
   501                 };
       
   502                 break;
       
   503             case "CMSCondCardMark":
       
   504                 // a card mark volatile barrier should be generated
       
   505                 // before the card mark strb from the StoreCM and the
       
   506                 // storestore barrier from the StoreCM should be elided
       
   507                 matches = new String[] {
       
   508                     "membar_release",
       
   509                     "dmb ish",
       
   510                     "cmpxchgw",
       
   511                     "membar_volatile",
       
   512                     "dmb ish",
       
   513                     "storestore (elided)",
       
   514                     "strb",
       
   515                     "membar_acquire",
       
   516                     "dmb ish",
       
   517                     "ret"
       
   518                 };
       
   519                 break;
       
   520             case "CMS":
       
   521                 // a volatile card mark membar should not be generated
       
   522                 // before the card mark strb from the StoreCM and the
       
   523                 // storestore barrier from the StoreCM should be generated
       
   524                 // as "dmb ishst"
       
   525                 matches = new String[] {
       
   526                     "membar_release",
       
   527                     "dmb ish",
       
   528                     "cmpxchgw",
       
   529                     "storestore",
       
   530                     "dmb ishst",
       
   531                     "strb",
       
   532                     "membar_acquire",
       
   533                     "dmb ish",
       
   534                     "ret"
       
   535                 };
       
   536                 break;
       
   537             }
       
   538         }
       
   539 
       
   540         checkCompile(iter, "testObj", matches, output);
       
   541     }
       
   542 
       
   543     // perform a check appropriate to the classname
       
   544 
       
   545     private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile) throws Throwable
       
   546     {
       
   547         // trace call to allow eyeball check of what is being checked
       
   548         System.out.println("checkoutput(" +
       
   549                            classname + ", " +
       
   550                            testType + ", " +
       
   551                            useBarriersForVolatile + ")\n" +
       
   552                            output.getOutput());
       
   553 
       
   554         switch (classname) {
       
   555         case "TestVolatileLoad":
       
   556             checkload(output, testType, useBarriersForVolatile);
       
   557             break;
       
   558         case "TestVolatileStore":
       
   559             checkstore(output, testType, useBarriersForVolatile);
       
   560             break;
       
   561         case "TestUnsafeVolatileLoad":
       
   562             checkload(output, testType, useBarriersForVolatile);
       
   563             break;
       
   564         case "TestUnsafeVolatileStore":
       
   565             checkstore(output, testType, useBarriersForVolatile);
       
   566             break;
       
   567         case "TestUnsafeVolatileCAS":
       
   568             checkcas(output, testType, useBarriersForVolatile);
       
   569             break;
       
   570         }
       
   571     }
       
   572 }