/* * Copyright (c) 2018, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * common code to run and validate tests of code generation for * volatile ops on AArch64 * * incoming args are * * where in {TestVolatileLoad, * TestVolatileStore, * TestUnsafeVolatileLoad, * TestUnsafeVolatileStore, * TestUnsafeVolatileCAS, * TestUnsafeVolatileWeakCAS, * TestUnsafeVolatileCAE, * TestUnsafeVolatileGAS} * and in {G1, * CMS, * CMSCondMark, * Serial, * Parallel, * Shenandoah, * ShenandoahIU} */ package compiler.c2.aarch64; import java.util.List; import java.util.ListIterator; import java.util.Iterator; import java.util.regex.Pattern; import java.io.*; import jdk.test.lib.Asserts; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import sun.hotspot.WhiteBox; // runner class that spawns a new JVM to exercises a combination of // volatile MemOp and GC. The ops are compiled with the dmb --> // ldar/stlr transforms either enabled or disabled. this runner parses // the PrintOptoAssembly output checking that the generated code is // correct. public class TestVolatiles { public void runtest(String classname, String testType) throws Throwable { // n.b. clients omit the package name for the class String fullclassname = "compiler.c2.aarch64." + classname; // build up a command line for the spawned JVM String[] procArgs; int argcount; // add one or two extra arguments according to test type // i.e. GC type plus GC conifg switch(testType) { case "G1": argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseG1GC"; break; case "Parallel": argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseParallelGC"; break; case "Serial": argcount = 9; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseSerialGC"; break; case "CMS": argcount = 10; procArgs = new String[argcount]; procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC"; procArgs[argcount - 2] = "-XX:-UseCondCardMark"; break; case "CMSCondMark": argcount = 10; procArgs = new String[argcount]; procArgs[argcount - 3] = "-XX:+UseConcMarkSweepGC"; procArgs[argcount - 2] = "-XX:+UseCondCardMark"; break; case "Shenandoah": argcount = 8; procArgs = new String[argcount]; procArgs[argcount - 2] = "-XX:+UseShenandoahGC"; break; case "ShenandoahIU": argcount = 11; procArgs = new String[argcount]; procArgs[argcount - 4] = "-XX:+UnlockExperimentalVMOptions"; procArgs[argcount - 3] = "-XX:+UseShenandoahGC"; procArgs[argcount - 2] = "-XX:ShenandoahGCMode=iu"; break; default: throw new RuntimeException("unexpected test type " + testType); } // fill in arguments common to all cases // the first round of test enables transform of barriers to // use acquiring loads and releasing stores by setting arg // zero appropriately. this arg is reset in the second run to // disable the transform. procArgs[0] = "-XX:-UseBarriersForVolatile"; procArgs[1] = "-XX:+UseCompressedOops"; procArgs[2] = "-XX:-TieredCompilation"; procArgs[3] = "-XX:+PrintOptoAssembly"; procArgs[4] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*"; procArgs[5] = "--add-exports"; procArgs[6] = "java.base/jdk.internal.misc=ALL-UNNAMED"; procArgs[argcount - 1] = fullclassname; runtest(classname, testType, false, true, procArgs); // rerun the test class without the transform applied and // check the alternative generation is as expected procArgs[0] = "-XX:+UseBarriersForVolatile"; runtest(classname, testType, true, true, procArgs); if (!classname.equals("TestUnsafeVolatileGAA")) { procArgs[0] = "-XX:-UseBarriersForVolatile"; procArgs[1] = "-XX:-UseCompressedOops"; runtest(classname, testType, false, false, procArgs); procArgs[0] = "-XX:+UseBarriersForVolatile"; runtest(classname, testType, true, false, procArgs); } } public void runtest(String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops, String[] procArgs) throws Throwable { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.stderrShouldBeEmptyIgnoreVMWarnings(); output.stdoutShouldNotBeEmpty(); output.shouldHaveExitValue(0); // check the output for the correct asm sequence as // appropriate to test class, test type and whether transform // was applied checkoutput(output, classname, testType, useBarriersForVolatile, useCompressedOops); } // skip through output returning a line containing the desireed // substring or null private String skipTo(Iterator iter, String substring) { while (iter.hasNext()) { String nextLine = iter.next(); if (nextLine.matches(".*" + substring + ".*")) { return nextLine; } } return null; } // locate the start of compiler output for the desired method and // then check that each expected instruction occurs in the output // in the order supplied. throw an excpetion if not found. // n.b. the spawned JVM's output is included in the exception // message to make it easeir to identify what is missing. private boolean checkCompile(Iterator iter, String methodname, String[] expected, OutputAnalyzer output, boolean do_throw) { // trace call to allow eyeball check of what we are checking against System.out.println("checkCompile(" + methodname + ","); String sepr = " { "; for (String s : expected) { System.out.print(sepr); System.out.print(s); sepr = ",\n "; } System.out.println(" })"); // look for the start of an opto assembly print block String match = skipTo(iter, Pattern.quote("{method}")); if (match == null) { if (do_throw) { throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput()); } return false; } // check the compiled method name is right match = skipTo(iter, Pattern.quote("- name:")); if (match == null) { if (do_throw) { throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput()); } return false; } if (!match.contains(methodname)) { if (do_throw) { throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput()); } return false; } // make sure we can match each expected term in order for (String s : expected) { match = skipTo(iter, s); if (match == null) { if (do_throw) { throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput()); } return false; } } return true; } // check for expected asm output from a volatile load private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); // we shoud see this same sequence for normal or unsafe volatile load // for both int and Object fields String[] matches; if (!useBarriersForVolatile) { matches = new String[] { "ldarw", "membar_acquire \\(elided\\)", "ret" }; } else { matches = new String[] { "ldrw", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, "testInt", matches, output, true); if (!useBarriersForVolatile) { matches = new String[] { useCompressedOops ? "ldarw?" : "ldar", "membar_acquire \\(elided\\)", "ret" }; } else { matches = new String[] { useCompressedOops ? "ldrw?" : "ldr", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, "testObj", matches, output, true); } // check for expected asm output from a volatile store private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); String[] matches; // non object stores are straightforward if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { "membar_release \\(elided\\)", "stlrw", "membar_volatile \\(elided\\)", "ret" }; } else { // this is the alternative sequence of instructions matches = new String[] { "membar_release", "dmb ish", "strw", "membar_volatile", "dmb ish", "ret" }; } checkCompile(iter, "testInt", matches, output, true); // object stores will be as above except for when the GC // introduces barriers for card marking if (!useBarriersForVolatile) { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "stlrw?" : "stlr", "membar_volatile \\(elided\\)", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "stlrw?" : "stlr", "membar_volatile", "dmb ish", "strb", "membar_volatile \\(elided\\)", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "stlrw?" : "stlr", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_volatile \\(elided\\)", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be // generated as "dmb ishst" matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "stlrw?" : "stlr", "storestore", "dmb ishst", "strb", "membar_volatile \\(elided\\)", "ret" }; break; case "Shenandoah": case "ShenandoahIU": // Shenandoah generates normal object graphs for // volatile stores matches = new String[] { "membar_release (elided)", "stlrw", "membar_volatile (elided)", "ret" }; break; } } else { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", "strb", "membar_volatile", "dmb ish", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "strw?" : "str", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_volatile", "dmb ish", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be generated // as "dmb ishst" matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "strw?" : "str", "storestore", "dmb ishst", "strb", "membar_volatile", "dmb ish", "ret" }; break; case "Shenandoah": case "ShenandoahIU": // Shenandoah generates normal object graphs for // volatile stores matches = new String[] { "membar_release", "dmb ish", "strw", "membar_volatile", "dmb ish", "ret" }; break; } } checkCompile(iter, "testObj", matches, output, true); } // check for expected asm output from a volatile cas private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); String[] matches; String[][] tests = { { "testInt", "cmpxchgw" }, { "testLong", "cmpxchg" }, { "testByte", "cmpxchgb" }, { "testShort", "cmpxchgs" }, }; for (String[] test : tests) { // non object stores are straightforward if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { "membar_release \\(elided\\)", test[1] + "_acq", "membar_acquire \\(elided\\)", "ret" }; } else { // this is the alternative sequence of instructions matches = new String[] { "membar_release", "dmb ish", test[1] + " ", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, test[0], matches, output, true); } // object stores will be as above except for when the GC // introduces barriers for card marking if (!useBarriersForVolatile) { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "membar_volatile", "dmb ish", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "storestore", "dmb ishst", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "Shenandoah": case "ShenandoahIU": // For volatile CAS, Shenanodoah generates normal // graphs with a shenandoah-specific cmpxchg matches = new String[] { "membar_release (elided)", "cmpxchgw_acq_shenandoah", "membar_acquire (elided)", "ret" }; break; } } else { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_acquire", "dmb ish", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_volatile", "dmb ish", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be generated // as "dmb ishst" matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "storestore", "dmb ishst", "strb", "membar_acquire", "dmb ish", "ret" }; break; } } checkCompile(iter, "testObj", matches, output, true); } private void checkcae(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { ListIterator iter = output.asLines().listIterator(); String[] matches; String[][] tests = { { "testInt", "cmpxchgw" }, { "testLong", "cmpxchg" }, { "testByte", "cmpxchgb" }, { "testShort", "cmpxchgs" }, }; for (String[] test : tests) { // non object stores are straightforward if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { "membar_release \\(elided\\)", test[1] + "_acq", "membar_acquire \\(elided\\)", "ret" }; } else { // this is the alternative sequence of instructions matches = new String[] { "membar_release", "dmb ish", test[1] + " ", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, test[0], matches, output, true); } // object stores will be as above except for when the GC // introduces barriers for card marking if (!useBarriersForVolatile) { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release \\(elided\\)", "strb", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "membar_acquire \\(elided\\)", "ret" }; // card marking store may be scheduled before or after // the cmpxchg so try both sequences. int idx = iter.nextIndex(); if (!checkCompile(iter, "testObj", matches, output, false)) { iter = output.asLines().listIterator(idx); matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "strb", "membar_acquire \\(elided\\)", "ret" }; checkCompile(iter, "testObj", matches, output, true); } return; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "membar_volatile", "dmb ish", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", "storestore", "dmb ishst", "strb", "membar_acquire \\(elided\\)", "ret" }; break; } } else { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_acquire", "dmb ish", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_volatile", "dmb ish", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be generated // as "dmb ishst" matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "cmpxchgw? " : "cmpxchg ", "storestore", "dmb ishst", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "Shenandoah": case "ShenandoahIU": // For volatile CAS, Shenanodoah generates normal // graphs with a shenandoah-specific cmpxchg matches = new String[] { "membar_release", "dmb ish", "cmpxchgw_shenandoah", "membar_acquire", "dmb ish", "ret" }; break; } } checkCompile(iter, "testObj", matches, output, true); } private void checkgas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { Iterator iter = output.asLines().listIterator(); String[] matches; String[][] tests = { { "testInt", "atomic_xchgw" }, { "testLong", "atomic_xchg" }, }; for (String[] test : tests) { // non object stores are straightforward if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { "membar_release \\(elided\\)", test[1] + "_acq", "membar_acquire \\(elided\\)", "ret" }; } else { // this is the alternative sequence of instructions matches = new String[] { "membar_release", "dmb ish", test[1] + " ", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, test[0], matches, output, true); } // object stores will be as above except for when the GC // introduces barriers for card marking if (!useBarriersForVolatile) { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "membar_volatile", "dmb ish", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire \\(elided\\)", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release \\(elided\\)", useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", "storestore", "dmb ishst", "strb", "membar_acquire \\(elided\\)", "ret" }; break; } } else { switch (testType) { default: // this is the basic sequence of instructions matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_acquire", "dmb ish", "ret" }; break; case "G1": // a card mark volatile barrier should be generated // before the card mark strb matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_volatile", "dmb ish", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMSCondMark": // a card mark volatile barrier should be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be elided matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "membar_volatile", "dmb ish", "storestore \\(elided\\)", "strb", "membar_acquire", "dmb ish", "ret" }; break; case "CMS": // a volatile card mark membar should not be generated // before the card mark strb from the StoreCM and the // storestore barrier from the StoreCM should be generated // as "dmb ishst" matches = new String[] { "membar_release", "dmb ish", useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", "storestore", "dmb ishst", "strb", "membar_acquire", "dmb ish", "ret" }; break; } } checkCompile(iter, "testObj", matches, output, true); } private void checkgaa(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable { Iterator iter = output.asLines().listIterator(); String[] matches; String[][] tests = { { "testInt", "get_and_addI" }, { "testLong", "get_and_addL" }, }; for (String[] test : tests) { // non object stores are straightforward if (!useBarriersForVolatile) { // this is the sequence of instructions for all cases matches = new String[] { "membar_release \\(elided\\)", test[1] + "_acq", "membar_acquire \\(elided\\)", "ret" }; } else { // this is the alternative sequence of instructions matches = new String[] { "membar_release", "dmb ish", test[1] + " ", "membar_acquire", "dmb ish", "ret" }; } checkCompile(iter, test[0], matches, output, true); } } // perform a check appropriate to the classname private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable { // trace call to allow eyeball check of what is being checked System.out.println("checkoutput(" + classname + ", " + testType + ", " + useBarriersForVolatile + ")\n" + output.getOutput()); switch (classname) { case "TestVolatileLoad": checkload(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestVolatileStore": checkstore(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileLoad": checkload(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileStore": checkstore(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileCAS": case "TestUnsafeVolatileWeakCAS": checkcas(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileCAE": checkcae(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileGAS": checkgas(output, testType, useBarriersForVolatile, useCompressedOops); break; case "TestUnsafeVolatileGAA": checkgaa(output, testType, useBarriersForVolatile); break; } } }