# HG changeset patch # User vlivanov # Date 1448408404 -3600 # Node ID 57d99d1614e02ddda86de01b97b6b10388ede772 # Parent eb43fec35c992d65037e8a1aadaa3edaf55953ef# Parent 3c271ee8fb98ebaf98675da6f2f69f9332687945 Merge diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Nov 25 00:40:04 2015 +0100 @@ -2285,7 +2285,7 @@ // Check if have the compiled code. if (!m->has_compiled_code()) { THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), - "out of space in CodeCache for method handle intrinsic", empty); + "Out of space in CodeCache for method handle intrinsic", empty); } } // Now grab the lock. We might have to throw away the new method, diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/InlineMatcherTest.java --- a/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/InlineMatcherTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -24,7 +24,8 @@ /* * @test InlineMatcherTest * @bug 8074095 - * @library /testlibrary /../../test/lib + * @library /testlibrary /test/lib + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI InlineMatcherTest diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityBase.java Wed Nov 25 00:40:04 2015 +0100 @@ -30,7 +30,7 @@ * java.management * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox.* + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCompilerDirectivesCompatibilityBase diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOff.java Wed Nov 25 00:40:04 2015 +0100 @@ -30,7 +30,7 @@ * java.management * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox.* + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityCommandOn.java Wed Nov 25 00:40:04 2015 +0100 @@ -30,7 +30,7 @@ * java.management * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox.* + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java --- a/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/TestCompilerDirectivesCompatibilityFlag.java Wed Nov 25 00:40:04 2015 +0100 @@ -30,7 +30,7 @@ * java.management * @build jdk.test.lib.* * @build jdk.test.lib.dcmd.* - * @build sun.hotspot.WhiteBox.* + * @build sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -26,7 +26,7 @@ * @bug 8137167 * @ignore 8140405 * @summary Tests jcmd to be able to clear directives added via options - * @library /testlibrary /../../test/lib /compiler/testlibrary ../share / + * @library /testlibrary /test/lib /compiler/testlibrary ../share / * @build ClearDirectivesFileStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -73,9 +73,6 @@ compileCommand.print(); builder.add(compileCommand); } - // print all directives before - builder.add(new JcmdCommand(Command.NONEXISTENT, null, null, - Scenario.Type.JCMD, Scenario.JcmdType.PRINT)); // clear the stack builder.add(new JcmdCommand(Command.NONEXISTENT, null, null, Scenario.Type.JCMD, Scenario.JcmdType.CLEAR)); diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -25,7 +25,7 @@ * @test * @bug 8137167 * @summary Tests clear JCMD command - * @library /testlibrary /../../test/lib /compiler/testlibrary ../share / + * @library /testlibrary /test/lib /compiler/testlibrary ../share / * @build ClearDirectivesStackTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -68,9 +68,6 @@ compileCommand.print(); builder.add(compileCommand); } - // print all directives before - builder.add(new JcmdCommand(Command.NONEXISTENT, null, null, - Scenario.Type.JCMD, Scenario.JcmdType.PRINT)); // clear the stack builder.add(new JcmdCommand(Command.NONEXISTENT, null, null, Scenario.Type.JCMD, Scenario.JcmdType.CLEAR)); diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +/* + * @test + * @bug 8137167 + * @summary Tests jcmd to be able to add a directive to compile only specified methods + * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @build pool.sub.* pool.subpack.* sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm compiler.compilercontrol.jcmd.PrintDirectivesTest + */ + +package compiler.compilercontrol.jcmd; + +import compiler.compilercontrol.share.AbstractTestBase; +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.scenario.Command; +import compiler.compilercontrol.share.scenario.CommandGenerator; +import compiler.compilercontrol.share.scenario.CompileCommand; +import compiler.compilercontrol.share.scenario.JcmdCommand; +import compiler.compilercontrol.share.scenario.Scenario; +import jdk.test.lib.Utils; + +import java.lang.reflect.Executable; + +public class PrintDirectivesTest extends AbstractTestBase { + private static final int AMOUNT = Utils.getRandomInstance().nextInt( + Integer.getInteger("compiler.compilercontrol.jcmd." + + "PrintDirectivesTest.amount", 20)); + private final CommandGenerator cmdGen = new CommandGenerator(); + + public static void main(String[] args) { + new PrintDirectivesTest().test(); + } + + @Override + public void test() { + Scenario.Builder builder = Scenario.getBuilder(); + // Add some commands with directives file + for (int i = 0; i < AMOUNT; i++) { + Executable exec = Utils.getRandomElement(METHODS).first; + MethodDescriptor methodDescriptor = getValidMethodDescriptor(exec); + Command command = cmdGen.generateCommand(); + if (command == Command.NONEXISTENT) { + // skip invalid command + command = Command.COMPILEONLY; + } + CompileCommand compileCommand = new CompileCommand(command, + methodDescriptor, cmdGen.generateCompiler(), + Scenario.Type.DIRECTIVE); + compileCommand.print(); + builder.add(compileCommand); + } + // print all directives + builder.add(new JcmdCommand(Command.NONEXISTENT, null, null, + Scenario.Type.JCMD, Scenario.JcmdType.PRINT)); + Scenario scenario = builder.build(); + scenario.execute(); + } +} \ No newline at end of file diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +package compiler.compilercontrol.jcmd; + +import compiler.compilercontrol.parser.HugeDirectiveUtil; +import compiler.compilercontrol.share.AbstractTestBase; +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.scenario.Executor; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.TimeLimitedRunner; +import jdk.test.lib.Utils; +import pool.PoolHelper; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public abstract class StressAddJcmdBase { + private static final int DIRECTIVES_AMOUNT = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddJcmdBase.directivesAmount", + 1000); + private static final int DIRECTIVE_FILES = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddJcmdBase.directiveFiles", + 5); + private static final List DESCRIPTORS = new PoolHelper() + .getAllMethods().stream() + .map(pair -> AbstractTestBase + .getValidMethodDescriptor(pair.first)) + .collect(Collectors.toList()); + + /** + * Performs test + */ + public void test() { + List commands = prepareCommands(); + Executor executor = new TimeLimitedExecutor(commands); + List outputAnalyzers = executor.execute(); + outputAnalyzers.get(0).shouldHaveExitValue(0); + } + + /** + * Makes connection to the test VM + * + * @param pid a pid of the VM under test + * @param commands a list of jcmd commands to be executed + * @return true if the test should continue invocation of this method + */ + protected abstract boolean makeConnection(int pid, List commands); + + /** + * Finish test executions + */ + protected void finish() { } + + private List prepareCommands() { + String[] files = new String[DIRECTIVE_FILES]; + for (int i = 0; i < DIRECTIVE_FILES; i++) { + files[i] = "directives" + i + ".json"; + HugeDirectiveUtil.createHugeFile(DESCRIPTORS, files[i], + DIRECTIVES_AMOUNT); + } + return Stream.of(files) + .map(file -> "Compiler.directives_add " + file) + .collect(Collectors.toList()); + } + + private class TimeLimitedExecutor extends Executor { + private final List jcmdCommands; + + public TimeLimitedExecutor(List jcmdCommands) { + /* There are no need to check the state */ + super(true, null, null, jcmdCommands); + this.jcmdCommands = jcmdCommands; + } + + @Override + protected OutputAnalyzer[] executeJCMD(int pid) { + TimeLimitedRunner runner = new TimeLimitedRunner( + Utils.DEFAULT_TEST_TIMEOUT, + Utils.TIMEOUT_FACTOR, + () -> makeConnection(pid, jcmdCommands)); + try { + runner.call(); + } catch (Exception e) { + throw new Error("Exception during the execution: " + e, e); + } + finish(); + return new OutputAnalyzer[0]; + } + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +/* + * @test + * @bug 8137167 + * @summary Tests jcmd to be able to add a lot of huge directive files with + * parallel executed jcmds until timeout has reached + * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @build StressAddMultiThreadedTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * compiler.compilercontrol.share.actions.* + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=360 compiler.compilercontrol.jcmd.StressAddMultiThreadedTest + */ + +package compiler.compilercontrol.jcmd; + +import jdk.test.lib.dcmd.PidJcmdExecutor; + +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class StressAddMultiThreadedTest extends StressAddJcmdBase { + private static final int THREADS; + private final BlockingQueue queue; + private final ExecutorService executor; + + static { + THREADS = Runtime.getRuntime().availableProcessors() + * Integer.getInteger("compiler.compilercontrol.jcmd" + + ".StressAddMultiThreadedTest.threadFactor", 10); + } + + public StressAddMultiThreadedTest() { + queue = new ArrayBlockingQueue<>(THREADS); + executor = new ThreadPoolExecutor(THREADS, THREADS, 100, + TimeUnit.MILLISECONDS, queue, + new ThreadPoolExecutor.CallerRunsPolicy()); + } + + public static void main(String[] args) { + new StressAddMultiThreadedTest().test(); + } + + @Override + protected boolean makeConnection(int pid, List commands) { + commands.forEach(command -> { + if (!executor.isShutdown()) { + executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid)) + .execute(command)); + } + }); + return !executor.isShutdown(); + } + + @Override + protected void finish() { + executor.shutdown(); + try { + executor.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new Error("Interrupted while awaiting for termination: " + e, + e); + } + executor.shutdownNow(); + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +/* + * @test + * @bug 8137167 + * @summary Tests jcmd to be able to add a lot of huge directives + * @library /testlibrary /test/lib /compiler/testlibrary ../share / + * @build StressAddSequentiallyTest pool.sub.* pool.subpack.* sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * compiler.compilercontrol.share.actions.* + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=300 compiler.compilercontrol.jcmd.StressAddSequentiallyTest + */ + +package compiler.compilercontrol.jcmd; + +import jdk.test.lib.dcmd.PidJcmdExecutor; + +import java.util.List; + +public class StressAddSequentiallyTest extends StressAddJcmdBase { + public static void main(String[] args) { + new StressAddSequentiallyTest().test(); + } + + @Override + protected boolean makeConnection(int pid, List commands) { + commands.forEach(command -> new PidJcmdExecutor(String.valueOf(pid)) + .execute(command)); + return true; + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java --- a/hotspot/test/compiler/compilercontrol/parser/DirectiveParser.java Wed Nov 25 01:17:28 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. 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. - */ - -/* - * @test - * @bug 8137167 - * @summary Tests directive json parser - * @library /testlibrary /../../test/lib ../share / - * @run driver compiler.compilercontrol.parser.DirectiveParser - */ - -package compiler.compilercontrol.parser; - -import compiler.compilercontrol.share.JSONFile; -import jdk.test.lib.Asserts; -import jdk.test.lib.OutputAnalyzer; -import jdk.test.lib.ProcessTools; -import jdk.test.lib.Utils; - -public class DirectiveParser { - private static final String ERROR_MSG = "VM should exit with error " - + "on incorrect JSON file: "; - private static final String EXPECTED_ERROR_STRING = "Parsing of compiler" - + " directives failed"; - - public static void main(String[] args) { - simpleTest(); - nonMatchingBrackets(); - arrayTest(); - emptyObjectTest(); - emptyFile(); - noFile(); - directory(); - } - - private static void simpleTest() { - String fileName = "simple.json"; - try (JSONFile file = new JSONFile(fileName)) { - file.write(JSONFile.Element.ARRAY) - .write(JSONFile.Element.OBJECT) - .write(JSONFile.Element.PAIR, "match") - .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"") - .write(JSONFile.Element.PAIR, "c2") - .write(JSONFile.Element.OBJECT) - .write(JSONFile.Element.PAIR, "inline") - .write(JSONFile.Element.ARRAY) - .write(JSONFile.Element.VALUE, "\"+*.indexOf\"") - .write(JSONFile.Element.VALUE, "\"-a.b\"") - .end() - .end() - .end() // end object - .write(JSONFile.Element.OBJECT) - .write(JSONFile.Element.PAIR, "match") - .write(JSONFile.Element.VALUE, "\"*.indexOf\"") - .write(JSONFile.Element.PAIR, "c1") - .write(JSONFile.Element.OBJECT) - .write(JSONFile.Element.PAIR, "enable") - .write(JSONFile.Element.VALUE, "false") - .end() - .end(); // end object - file.end(); - } - OutputAnalyzer output = execute(fileName); - output.shouldHaveExitValue(0); - output.shouldNotContain(EXPECTED_ERROR_STRING); - } - - private static void nonMatchingBrackets() { - String fileName = "non-matching.json"; - try (JSONFile file = new JSONFile(fileName)) { - file.write(JSONFile.Element.ARRAY) - .write(JSONFile.Element.OBJECT) - .write(JSONFile.Element.PAIR, "match") - .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"") - .end(); - // don't write matching } - } - OutputAnalyzer output = execute(fileName); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non matching " - + "brackets"); - output.shouldContain(EXPECTED_ERROR_STRING); - } - - private static void arrayTest() { - String fileName = "array.json"; - try (JSONFile file = new JSONFile(fileName)) { - file.write(JSONFile.Element.ARRAY); - file.end(); - } - OutputAnalyzer output = execute(fileName); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty array"); - } - - private static void emptyObjectTest() { - String fileName = "emptyObject.json"; - try (JSONFile file = new JSONFile(fileName)) { - file.write(JSONFile.Element.OBJECT); - file.end(); - } - OutputAnalyzer output = execute(fileName); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty object " - + "without any match"); - output.shouldContain(EXPECTED_ERROR_STRING); - } - - private static void emptyFile() { - String fileName = "empty.json"; - try (JSONFile file = new JSONFile(fileName)) { - // empty - } - OutputAnalyzer output = execute(fileName); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty file"); - output.shouldContain(EXPECTED_ERROR_STRING); - } - - private static void noFile() { - OutputAnalyzer output = execute("nonexistent.json"); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non existing " - + "file"); - } - - private static void directory() { - OutputAnalyzer output = execute(Utils.TEST_SRC); - Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "directory as " - + "a name"); - } - - private static OutputAnalyzer execute(String fileName) { - OutputAnalyzer output; - try { - output = ProcessTools.executeTestJvm( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:CompilerDirectivesFile=" + fileName, - "-version"); - } catch (Throwable thr) { - throw new Error("Execution failed", thr); - } - return output; - } -} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/parser/DirectiveParserTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/parser/DirectiveParserTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +/* + * @test + * @bug 8137167 + * @summary Tests directive json parser + * @library /testlibrary /test/lib ../share / + * @run driver compiler.compilercontrol.parser.DirectiveParserTest + */ + +package compiler.compilercontrol.parser; + +import compiler.compilercontrol.share.JSONFile; +import jdk.test.lib.Asserts; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Utils; + +public class DirectiveParserTest { + private static final String ERROR_MSG = "VM should exit with error " + + "on incorrect JSON file: "; + private static final String EXPECTED_ERROR_STRING = "Parsing of compiler" + + " directives failed"; + + public static void main(String[] args) { + simpleTest(); + nonMatchingBrackets(); + arrayTest(); + emptyObjectTest(); + emptyFile(); + noFile(); + directory(); + } + + private static void simpleTest() { + String fileName = "simple.json"; + try (JSONFile file = new JSONFile(fileName)) { + file.write(JSONFile.Element.ARRAY) + .write(JSONFile.Element.OBJECT) + .write(JSONFile.Element.PAIR, "match") + .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"") + .write(JSONFile.Element.PAIR, "c2") + .write(JSONFile.Element.OBJECT) + .write(JSONFile.Element.PAIR, "inline") + .write(JSONFile.Element.ARRAY) + .write(JSONFile.Element.VALUE, "\"+*.indexOf\"") + .write(JSONFile.Element.VALUE, "\"-a.b\"") + .end() + .end() + .end() // end object + .write(JSONFile.Element.OBJECT) + .write(JSONFile.Element.PAIR, "match") + .write(JSONFile.Element.VALUE, "\"*.indexOf\"") + .write(JSONFile.Element.PAIR, "c1") + .write(JSONFile.Element.OBJECT) + .write(JSONFile.Element.PAIR, "enable") + .write(JSONFile.Element.VALUE, "false") + .end() + .end(); // end object + file.end(); + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + output.shouldHaveExitValue(0); + output.shouldNotContain(EXPECTED_ERROR_STRING); + } + + private static void nonMatchingBrackets() { + String fileName = "non-matching.json"; + try (JSONFile file = new JSONFile(fileName)) { + file.write(JSONFile.Element.ARRAY) + .write(JSONFile.Element.OBJECT) + .write(JSONFile.Element.PAIR, "match") + .write(JSONFile.Element.VALUE, "\"java/lang/String.*\"") + .end(); + // don't write matching } + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non matching " + + "brackets"); + output.shouldContain(EXPECTED_ERROR_STRING); + } + + private static void arrayTest() { + String fileName = "array.json"; + try (JSONFile file = new JSONFile(fileName)) { + file.write(JSONFile.Element.ARRAY); + file.end(); + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty array"); + } + + private static void emptyObjectTest() { + String fileName = "emptyObject.json"; + try (JSONFile file = new JSONFile(fileName)) { + file.write(JSONFile.Element.OBJECT); + file.end(); + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty object " + + "without any match"); + output.shouldContain(EXPECTED_ERROR_STRING); + } + + private static void emptyFile() { + String fileName = "empty.json"; + try (JSONFile file = new JSONFile(fileName)) { + // empty + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "empty file"); + output.shouldContain(EXPECTED_ERROR_STRING); + } + + private static void noFile() { + OutputAnalyzer output = HugeDirectiveUtil.execute("nonexistent.json"); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "non existing " + + "file"); + } + + private static void directory() { + OutputAnalyzer output = HugeDirectiveUtil.execute(Utils.TEST_SRC); + Asserts.assertNE(output.getExitValue(), 0, ERROR_MSG + "directory as " + + "a name"); + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/parser/DirectiveStressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/parser/DirectiveStressTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +/* + * @test + * @bug 8137167 + * @summary Stress directive json parser + * @library /testlibrary /test/lib ../share / + * @run driver compiler.compilercontrol.parser.DirectiveStressTest + */ + +package compiler.compilercontrol.parser; + +import compiler.compilercontrol.share.AbstractTestBase; +import compiler.compilercontrol.share.JSONFile; +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.scenario.DirectiveWriter; +import jdk.test.lib.OutputAnalyzer; +import pool.PoolHelper; + +import java.util.List; +import java.util.stream.Collectors; + +public class DirectiveStressTest { + private static final int AMOUNT = Integer.getInteger( + "compiler.compilercontrol.parser.DirectiveStressTest.amount", + Short.MAX_VALUE * 2 + 2); + private static final List DESCRIPTORS + = new PoolHelper().getAllMethods().stream() + .map(pair -> AbstractTestBase.getValidMethodDescriptor( + pair.first)) + .collect(Collectors.toList()); + private static final String EXPECTED_MESSAGE = " compiler directives added"; + + public static void main(String[] args) { + hugeFileTest(); + hugeObjectTest(); + } + + /* + * Creates file with AMOUNT of options in match block + */ + private static void hugeObjectTest() { + String fileName = "hugeObject.json"; + try (DirectiveWriter file = new DirectiveWriter(fileName)) { + file.write(JSONFile.Element.ARRAY); + HugeDirectiveUtil.createMatchObject(DESCRIPTORS, file, AMOUNT); + file.end(); // end array block + } + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + output.shouldHaveExitValue(0); + output.shouldContain(1 + EXPECTED_MESSAGE); + output.shouldNotContain(HugeDirectiveUtil.EXPECTED_ERROR_STRING); + } + + /* + * Creates huge valid file with AMOUNT of match directives + */ + private static void hugeFileTest() { + String fileName = "hugeFile.json"; + HugeDirectiveUtil.createHugeFile(DESCRIPTORS, fileName, AMOUNT); + OutputAnalyzer output = HugeDirectiveUtil.execute(fileName); + output.shouldHaveExitValue(0); + output.shouldContain(AMOUNT + EXPECTED_MESSAGE); + output.shouldNotContain(HugeDirectiveUtil.EXPECTED_ERROR_STRING); + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/parser/HugeDirectiveUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/parser/HugeDirectiveUtil.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +package compiler.compilercontrol.parser; + +import compiler.compilercontrol.share.JSONFile; +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.scenario.DirectiveWriter; +import compiler.compilercontrol.share.scenario.Scenario; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.Utils; + +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +/** + * Creates a huge directive file + */ +public final class HugeDirectiveUtil { + private static final Random RANDOM = Utils.getRandomInstance(); + protected static final String EXPECTED_ERROR_STRING = "Parsing of compiler " + + "directives failed"; + + private HugeDirectiveUtil() { } + + /** + * Creates huge file with specified amount of directives + * + * @param descriptors a list of descriptors to be randomly used + * in match and inline blocks + * @param fileName a directives file name to be created + * @param amount an amount of match objects + */ + public static void createHugeFile(List descriptors, + String fileName, int amount) { + try (DirectiveWriter file = new DirectiveWriter(fileName)) { + file.write(JSONFile.Element.ARRAY); + for (int i = 0; i < amount; i++) { + createMatchObject(descriptors, file, 1); + } + file.end(); + } + } + + /** + * Creates match object in the given file with specified size + * + * @param descriptors a list of method descriptors to be used + * @param file a directive file to write at + * @param objectSize a size of the match object + */ + public static void createMatchObject(List descriptors, + DirectiveWriter file, int objectSize) { + // get random amount of methods for the match + List methods = getRandomDescriptors(descriptors); + file.match(methods.toArray(new String[methods.size()])); + for (int i = 0; i < objectSize; i++) { + // emit compiler block + file.emitCompiler(Utils.getRandomElement( + Scenario.Compiler.values())); + file.option(Utils.getRandomElement(DirectiveWriter.Option.values()), + RANDOM.nextBoolean()); + file.end(); // ends compiler block + + // add standalone option + file.option(Utils.getRandomElement(DirectiveWriter.Option.values()), + RANDOM.nextBoolean()); + } + // add inline block with random inlinees + methods = getRandomDescriptors(descriptors).stream() + .map(s -> (RANDOM.nextBoolean() ? "+" : "-") + s) + .collect(Collectors.toList()); + file.inline(methods.toArray(new String[methods.size()])); + + // end match block + file.end(); + } + + private static List getRandomDescriptors( + List descriptors) { + int amount = 1 + RANDOM.nextInt(descriptors.size() - 1); + int skipAmount = RANDOM.nextInt(descriptors.size() - amount); + return descriptors.stream() + .skip(skipAmount) + .limit(amount) + .map(MethodDescriptor::getString) + .collect(Collectors.toList()); + } + + protected static OutputAnalyzer execute(String fileName) { + OutputAnalyzer output; + try { + output = ProcessTools.executeTestJvm( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:CompilerDirectivesFile=" + fileName, + "-version"); + } catch (Throwable thr) { + throw new Error("Execution failed with: " + thr, thr); + } + return output; + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java --- a/hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/share/actions/BaseAction.java Wed Nov 25 00:40:04 2015 +0100 @@ -55,11 +55,24 @@ pair -> pair.first)); } + /* + * args[0] is a port to connect + * args[1] is an optional parameter that shows that the state map should be + * passed + */ public static void main(String[] args) { if (args.length < 1) { throw new Error("TESTBUG: requires port as parameter: " + Arrays.toString(args)); } + boolean getStates = false; + if (args.length == 2) { + if ("states".equals(args[1])) { + getStates = true; + } else { + throw new Error("TESTBUG: incorrect argument: "+ args[1]); + } + } int pid; try { pid = ProcessTools.getProcessId(); @@ -78,11 +91,15 @@ // send own pid to execute jcmd if needed out.println(String.valueOf(pid)); out.flush(); - lines = in.lines().collect(Collectors.toList()); + if (getStates) { + lines = in.lines().collect(Collectors.toList()); + check(decodeMap(lines)); + } else { + in.readLine(); + } } catch (IOException e) { throw new Error("Error on performing network operation", e); } - check(decodeMap(lines)); } private static Map decodeMap(List lines) { diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java --- a/hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/share/processors/CommandProcessor.java Wed Nov 25 00:40:04 2015 +0100 @@ -24,8 +24,10 @@ package compiler.compilercontrol.share.processors; import compiler.compilercontrol.share.scenario.CompileCommand; +import jdk.test.lib.Asserts; import jdk.test.lib.OutputAnalyzer; +import java.util.Iterator; import java.util.List; import java.util.function.Consumer; @@ -33,26 +35,56 @@ * Checks that output contains a string with commands and full method pattern */ public class CommandProcessor implements Consumer { - protected final List commands; + private static final String INVALID_COMMAND_MSG = "CompileCommand: " + + "\\b(unrecognized command|Bad pattern|" + + "An error occurred during parsing)\\b"; + private final Iterator nonQuietedIterator; + private final Iterator quietedIterator; - public CommandProcessor(List commands) { - this.commands = commands; + public CommandProcessor(List nonQuieted, + List quieted) { + this.nonQuietedIterator = nonQuieted.iterator(); + this.quietedIterator = quieted.iterator(); } @Override public void accept(OutputAnalyzer outputAnalyzer) { - for (CompileCommand command : commands) { + try { + outputAnalyzer.asLines().stream() + .filter(s -> s.startsWith("CompileCommand:")) + .forEachOrdered(this::check); + } catch (Exception e) { + System.err.println(outputAnalyzer.getOutput()); + throw e; + } + } + + private void check(String input) { + if (nonQuietedIterator.hasNext()) { + CompileCommand command = nonQuietedIterator.next(); if (command.isValid()) { - outputAnalyzer.shouldContain("CompileCommand: " - + command.command.name + " " - + command.methodDescriptor.getCanonicalString()); - outputAnalyzer.shouldNotContain("CompileCommand: An error " - + "occurred during parsing"); + Asserts.assertTrue(input.contains(getOutputString(command)), + getOutputString(command) + "missing in output"); } else { - outputAnalyzer.shouldMatch("(CompileCommand: )" - + "(unrecognized command)|(Bad pattern)|" - + "(An error occurred during parsing)"); + Asserts.assertTrue(input.matches(INVALID_COMMAND_MSG), + "Error message missing for: " + getOutputString( + command)); + } + } else if (quietedIterator.hasNext()) { + CompileCommand command = quietedIterator.next(); + if (command.isValid()) { + Asserts.assertFalse(input.contains(getOutputString(command))); + } else { + Asserts.assertTrue(input.matches(INVALID_COMMAND_MSG), + "Error message missing for: " + getOutputString( + command)); } } } + + private String getOutputString(CompileCommand command) { + return "CompileCommand: " + + command.command.name + " " + + command.methodDescriptor.getCanonicalString(); + } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/processors/PrintDirectivesProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/processors/PrintDirectivesProcessor.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +package compiler.compilercontrol.share.processors; + +import compiler.compilercontrol.share.method.MethodDescriptor; +import compiler.compilercontrol.share.scenario.CompileCommand; +import jdk.test.lib.Asserts; +import jdk.test.lib.OutputAnalyzer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class PrintDirectivesProcessor + implements Consumer> { + private final List commands; + private static final Pattern MATCH_PATTERN + = Pattern.compile(" matching: (.*)"); + + public PrintDirectivesProcessor(List commands) { + this.commands = commands; + } + + @Override + public void accept(List outputAnalyzers) { + List directives = new ArrayList<>(); + outputAnalyzers.forEach(outputAnalyzer -> + directives.addAll(getDirectives(outputAnalyzer))); + List expectedDirectives = commands.stream() + .map(cc -> cc.methodDescriptor) + .map(MethodDescriptor::getCanonicalString) + .collect(Collectors.toList()); + + if (directives.size() != expectedDirectives.size()) { + printDirectives(directives, expectedDirectives); + throw new AssertionError(String.format("Different number of " + + "directives. Expected: %d, actual: %d", + expectedDirectives.size(), directives.size())); + } + for (int i = 0; i < directives.size(); i++) { + if (!directives.get(i).equals(expectedDirectives.get(i))) { + printDirectives(directives, expectedDirectives); + throw new AssertionError( + String.format("Directives differ at %d, expected:%s%n", + i, expectedDirectives.get(i))); + } + } + } + + private List getDirectives(OutputAnalyzer outputAnalyzer) { + List directives = new ArrayList<>(); + List inputStrings = outputAnalyzer.asLines(); + Iterator iterator = inputStrings.iterator(); + while (iterator.hasNext()) { + String input = iterator.next(); + if (input.equals("Directive:")) { + Asserts.assertTrue(iterator.hasNext(), "inconsistent directive" + + "printed into the output"); + String matchString = iterator.next(); + Matcher matcher = MATCH_PATTERN.matcher(matchString); + Asserts.assertTrue(matcher.matches(), "Incorrect matching " + + "string in directive"); + directives.add(matcher.group(1)); + } + } + return directives; + } + + private void printDirectives(List directives, + List expected) { + System.err.println("Actual directives: " + directives); + System.err.println("Expected directives: " + expected); + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/processors/QuietProcessor.java --- a/hotspot/test/compiler/compilercontrol/share/processors/QuietProcessor.java Wed Nov 25 01:17:28 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. 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. - */ - -package compiler.compilercontrol.share.processors; - -import compiler.compilercontrol.share.scenario.CompileCommand; -import jdk.test.lib.OutputAnalyzer; - -import java.util.List; -import java.util.function.Consumer; - -public class QuietProcessor implements Consumer { - private final List commands; - - public QuietProcessor(List compileCommands) { - commands = compileCommands; - } - - @Override - public void accept(OutputAnalyzer outputAnalyzer) { - for (CompileCommand command : commands) { - if (command.isValid()) { - outputAnalyzer.shouldNotContain("CompileCommand: " - + command.command.name + " " - + command.methodDescriptor.getCanonicalString()); - outputAnalyzer.shouldNotContain("CompileCommand: An error " - + "occurred during parsing"); - } else { - outputAnalyzer.shouldMatch("(CompileCommand: )" - + "(unrecognized command)|(Bad pattern)|" - + "(An error occurred during parsing)"); - } - } - } -} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/scenario/DirectiveBuilder.java --- a/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveBuilder.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/share/scenario/DirectiveBuilder.java Wed Nov 25 00:40:04 2015 +0100 @@ -36,6 +36,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.concurrent.Callable; +import java.util.stream.Collectors; /** * Directive file and state builder class @@ -66,7 +67,10 @@ @Override public List getCompileCommands() { - throw new Error("TESTBUG: isn't applicable for directives"); + return matchBlocks.keySet().stream() + // only method descriptor is required to check print_directives + .map(md -> new CompileCommand(null, md, null, null)) + .collect(Collectors.toList()); } @Override diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/scenario/Executor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/compilercontrol/share/scenario/Executor.java Wed Nov 25 00:40:04 2015 +0100 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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. + */ + +package compiler.compilercontrol.share.scenario; + +import compiler.compilercontrol.share.actions.BaseAction; +import jdk.test.lib.Asserts; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; +import jdk.test.lib.dcmd.CommandExecutor; +import jdk.test.lib.dcmd.PidJcmdExecutor; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.lang.reflect.Executable; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class Executor { + private final boolean isValid; + private final List vmOptions; + private final Map states; + private final List jcmdCommands; + private OutputAnalyzer[] jcmdOutputAnalyzers; + + /** + * Constructor + * + * @param isValid shows that the input given to the VM is valid and + * VM shouldn't fail + * @param vmOptions a list of VM input options + * @param states a state map, or null for the non-checking execution + * @param jcmdCommands a list of diagnostic commands to be preformed + * on test VM + */ + public Executor(boolean isValid, List vmOptions, + Map states, List jcmdCommands) { + this.isValid = isValid; + if (vmOptions == null) { + this.vmOptions = new ArrayList<>(); + } else { + this.vmOptions = vmOptions; + } + this.states = states; + this.jcmdCommands = jcmdCommands; + } + + /** + * Executes separate VM a gets an OutputAnalyzer instance with the results + * of execution + */ + public List execute() { + // Add class name that would be executed in a separate VM + String classCmd = BaseAction.class.getName(); + vmOptions.add(classCmd); + OutputAnalyzer output; + try (ServerSocket serverSocket = new ServerSocket(0)) { + if (isValid) { + // Get port test VM will connect to + int port = serverSocket.getLocalPort(); + if (port == -1) { + throw new Error("Socket is not bound: " + port); + } + vmOptions.add(String.valueOf(port)); + if (states != null) { + // add flag to show that there should be state map passed + vmOptions.add("states"); + } + // Start separate thread to connect with test VM + new Thread(() -> connectTestVM(serverSocket)).start(); + } + // Start test VM + output = ProcessTools.executeTestJvmAllArgs( + vmOptions.toArray(new String[vmOptions.size()])); + } catch (Throwable thr) { + throw new Error("Execution failed: " + thr.getMessage(), thr); + } + + List outputList = new ArrayList<>(); + outputList.add(output); + if (jcmdOutputAnalyzers != null) { + Collections.addAll(outputList, jcmdOutputAnalyzers); + } + return outputList; + } + + /* + * Performs connection with a test VM, sends method states and performs + * JCMD operations on a test VM. + */ + private void connectTestVM(ServerSocket serverSocket) { + /* + * There are no way to prove that accept was invoked before we started + * test VM that connects to this serverSocket. Connection timeout is + * enough + */ + try ( + Socket socket = serverSocket.accept(); + PrintWriter pw = new PrintWriter(socket.getOutputStream(), + true); + BufferedReader in = new BufferedReader(new InputStreamReader( + socket.getInputStream()))) { + // Get pid of the executed process + int pid = Integer.parseInt(in.readLine()); + Asserts.assertNE(pid, 0, "Got incorrect pid"); + jcmdOutputAnalyzers = executeJCMD(pid); + if (states != null) { + // serialize and send state map + states.forEach((executable, state) -> { + pw.println("{"); + pw.println(executable.toGenericString()); + pw.println(state.toString()); + pw.println("}"); + }); + } else { + pw.println(); + } + } catch (IOException e) { + throw new Error("Failed to write data: " + e.getMessage(), e); + } + } + + // Executes all diagnostic commands + protected OutputAnalyzer[] executeJCMD(int pid) { + int size = jcmdCommands.size(); + OutputAnalyzer[] outputArray = new OutputAnalyzer[size]; + CommandExecutor jcmdExecutor = new PidJcmdExecutor(String.valueOf(pid)); + for (int i = 0; i < size; i++) { + outputArray[i] = jcmdExecutor.execute(jcmdCommands.get(i)); + } + return outputArray; + } +} diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/scenario/JcmdStateBuilder.java --- a/hotspot/test/compiler/compilercontrol/share/scenario/JcmdStateBuilder.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/share/scenario/JcmdStateBuilder.java Wed Nov 25 00:40:04 2015 +0100 @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import java.util.stream.Collectors; public class JcmdStateBuilder implements StateBuilder { private static final List>> METHODS @@ -44,7 +45,6 @@ private final DirectiveBuilder directiveBuilder; private Map> matchBlocks = new LinkedHashMap<>(); - private List commands = new ArrayList<>(); private boolean isFileValid = true; public JcmdStateBuilder(String fileName) { @@ -53,7 +53,6 @@ @Override public void add(JcmdCommand compileCommand) { - commands.add(compileCommand); switch (compileCommand.jcmdType) { case ADD: directiveBuilder.add(compileCommand); @@ -159,6 +158,15 @@ @Override public List getCompileCommands() { - return commands; + if (isFileValid) { + return matchBlocks.keySet().stream() + /* only method descriptor is required + to check print_directives */ + .map(md -> new JcmdCommand(null, md, null, null, + Scenario.JcmdType.ADD)) + .collect(Collectors.toList()); + } else { + return new ArrayList<>(); + } } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java --- a/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java Wed Nov 25 00:40:04 2015 +0100 @@ -23,29 +23,18 @@ package compiler.compilercontrol.share.scenario; -import compiler.compilercontrol.share.actions.BaseAction; import compiler.compilercontrol.share.method.MethodDescriptor; import compiler.compilercontrol.share.processors.CommandProcessor; import compiler.compilercontrol.share.processors.LogProcessor; +import compiler.compilercontrol.share.processors.PrintDirectivesProcessor; import compiler.compilercontrol.share.processors.PrintProcessor; -import compiler.compilercontrol.share.processors.QuietProcessor; import jdk.test.lib.Asserts; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.Pair; -import jdk.test.lib.ProcessTools; -import jdk.test.lib.dcmd.CommandExecutorException; -import jdk.test.lib.dcmd.JcmdExecutor; import pool.PoolHelper; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; import java.lang.reflect.Executable; -import java.net.ServerSocket; -import java.net.Socket; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; @@ -60,18 +49,18 @@ */ public final class Scenario { private final boolean isValid; - private final List vmopts; private final Map states; private final List> processors; - private final List jcmdExecCommands; + private final Executor executor; + private final Consumer> jcmdProcessor; private Scenario(boolean isValid, List vmopts, Map states, List compileCommands, - List jcmdCommands) { + List jcmdCommands, + List directives) { this.isValid = isValid; - this.vmopts = vmopts; this.states = states; processors = new ArrayList<>(); processors.add(new LogProcessor(states)); @@ -87,10 +76,10 @@ nonQuieted.add(cc); } } - processors.add(new CommandProcessor(nonQuieted)); - processors.add(new QuietProcessor(quieted)); - jcmdExecCommands = new ArrayList<>(); + processors.add(new CommandProcessor(nonQuieted, quieted)); + List jcmdExecCommands = new ArrayList<>(); boolean addCommandMet = false; + boolean printCommandMet = false; for (JcmdCommand cmd : jcmdCommands) { switch (cmd.jcmdType) { case ADD: @@ -99,97 +88,40 @@ } addCommandMet = true; break; + case PRINT: + printCommandMet = true; + break; default: jcmdExecCommands.add(cmd.jcmdType.command); break; } } + // Add print command only in the end to get directives printed + if (printCommandMet) { + jcmdExecCommands.add(JcmdType.PRINT.command); + } + jcmdProcessor = new PrintDirectivesProcessor(directives); + executor = new Executor(isValid, vmopts, states, jcmdExecCommands); } /** * Executes scenario */ public void execute() { - // Construct execution command with CompileCommand and class - List argsList = new ArrayList<>(); - // Add VM options - argsList.addAll(vmopts); - // Add class name that would be executed in a separate VM - String classCmd = BaseAction.class.getName(); - argsList.add(classCmd); - OutputAnalyzer output; - try (ServerSocket serverSocket = new ServerSocket(0)) { - if (isValid) { - // Get port test VM will connect to - int port = serverSocket.getLocalPort(); - if (port == -1) { - throw new Error("Socket is not bound: " + port); - } - argsList.add(String.valueOf(port)); - // Start separate thread to connect with test VM - new Thread(() -> connectTestVM(serverSocket)).start(); - } - // Start test VM - output = ProcessTools.executeTestJvmAllArgs( - argsList.toArray(new String[argsList.size()])); - } catch (Throwable thr) { - throw new Error("Execution failed", thr); - } + List outputList = executor.execute(); + // The first one contains output from the test VM + OutputAnalyzer mainOuput = outputList.get(0); if (isValid) { - output.shouldHaveExitValue(0); - for (Consumer processor : processors) { - processor.accept(output); - } + mainOuput.shouldHaveExitValue(0); + processors.forEach(processor -> processor.accept(mainOuput)); + // only the last output contains directives got from print command + List last = new ArrayList<>(); + last.add(outputList.get(outputList.size() - 1)); + jcmdProcessor.accept(last); } else { - Asserts.assertNE(output.getExitValue(), 0, "VM should exit with " + Asserts.assertNE(mainOuput.getExitValue(), 0, "VM should exit with " + "error for incorrect directives"); - output.shouldContain("Parsing of compiler directives failed"); - } - } - - /* - * Performs connection with a test VM, sends method states and performs - * JCMD operations on a test VM. - */ - private void connectTestVM(ServerSocket serverSocket) { - /* - * There are no way to prove that accept was invoked before we started - * test VM that connects to this serverSocket. Connection timeout is - * enough - */ - try ( - Socket socket = serverSocket.accept(); - PrintWriter pw = new PrintWriter(socket.getOutputStream(), - true); - BufferedReader in = new BufferedReader(new InputStreamReader( - socket.getInputStream()))) { - // Get pid of the executed process - int pid = Integer.parseInt(in.readLine()); - Asserts.assertNE(pid, 0, "Got incorrect pid"); - executeJCMD(pid); - // serialize and send state map - for (Executable x : states.keySet()) { - pw.println("{"); - pw.println(x.toGenericString()); - pw.println(states.get(x).toString()); - pw.println("}"); - } - } catch (IOException e) { - throw new Error("Failed to write data", e); - } - } - - // Executes all diagnostic commands - private void executeJCMD(int pid) { - for (String command : jcmdExecCommands) { - new JcmdExecutor() { - @Override - protected List createCommandLine(String cmd) - throws CommandExecutorException { - return Arrays.asList(jcmdBinary, Integer.toString(pid), - cmd); - } - }.execute(command); + mainOuput.shouldContain("Parsing of compiler directives failed"); } } @@ -265,6 +197,7 @@ private final Map> builders = new HashMap<>(); private final JcmdStateBuilder jcmdStateBuilder; + private final List jcmdCommands = new ArrayList<>(); public Builder() { builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName)); @@ -279,6 +212,7 @@ Collections.addAll(vmopts, vmOptions); if (compileCommand.type == Type.JCMD) { jcmdStateBuilder.add((JcmdCommand) compileCommand); + jcmdCommands.add((JcmdCommand) compileCommand); } else { StateBuilder builder = builders.get( compileCommand.type); @@ -301,11 +235,9 @@ Map directiveFileStates = builders.get(Type.DIRECTIVE).getStates(); - // get all jcmd commands - List jcmdCommands = jcmdStateBuilder - .getCompileCommands(); + // check if directives stack was cleared by jcmd boolean isClearedState = false; - if (jcmdClearedState(jcmdCommands)) { + if (jcmdContainsCommand(JcmdType.CLEAR)) { isClearedState = true; } @@ -339,6 +271,16 @@ ccList.addAll(builders.get(Type.OPTION).getCompileCommands()); ccList.addAll(builders.get(Type.FILE).getCompileCommands()); + // Create a list of directives to check which one was printed + List directives = new ArrayList<>(); + if (jcmdContainsCommand(JcmdType.PRINT)) { + if (!isClearedState) { + directives.addAll(builders.get(Type.DIRECTIVE) + .getCompileCommands()); + } + directives.addAll(jcmdStateBuilder.getCompileCommands()); + } + // Get all VM options after we build all states and files List options = new ArrayList<>(); options.addAll(vmopts); @@ -348,13 +290,13 @@ } options.addAll(jcmdStateBuilder.getOptions()); return new Scenario(isValid, options, finalStates, ccList, - jcmdCommands); + jcmdCommands, directives); } - // shows if jcmd have passed a clear command - private boolean jcmdClearedState(List jcmdCommands) { + // shows if jcmd have passed a specified jcmd command type + private boolean jcmdContainsCommand(JcmdType type) { for (JcmdCommand jcmdCommand : jcmdCommands) { - if (jcmdCommand.jcmdType == JcmdType.CLEAR) { + if (jcmdCommand.jcmdType == type) { return true; } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/jvmci/common/CTVMUtilities.java --- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java Wed Nov 25 00:40:04 2015 +0100 @@ -23,10 +23,25 @@ package compiler.jvmci.common; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Executable; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Parameter; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.tree.ClassNode; +import jdk.test.lib.Utils; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -71,4 +86,73 @@ this.entryPoint = entryPoint; } } + public static Map getBciToLineNumber(Executable method) { + Map lineNumbers = new TreeMap<>(); + try { + ClassReader cr = new ClassReader(method.getDeclaringClass() + .getName()); + ClassNode cn = new ClassNode(); + cr.accept(cn, ClassReader.EXPAND_FRAMES); + + Map labels = new HashMap<>(); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method); + cr.accept(cv, ClassReader.EXPAND_FRAMES); + labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v)); + } catch (IOException e) { + throw new Error("TEST BUG " + e, e); + } + boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers()) + || Modifier.isNative(method.getModifiers()); + if (lineNumbers.isEmpty() && !isEmptyMethod) { + throw new Error(method + " doesn't contains the line numbers table " + +"(the method marked neither abstract nor native)"); + } + return lineNumbers; + } + + private static class ClassVisitorForLabels extends ClassVisitor { + private final Map lineNumbers; + private final String targetName; + private final String targetDesc; + + public ClassVisitorForLabels(ClassWriter cw, Map lines, + Executable target) { + super(Opcodes.ASM5, cw); + this.lineNumbers = lines; + + StringBuilder builder = new StringBuilder("("); + for (Parameter parameter : target.getParameters()) { + builder.append(Utils.toJVMTypeSignature(parameter.getType())); + } + builder.append(")"); + if (target instanceof Constructor) { + targetName = ""; + builder.append("V"); + } else { + targetName = target.getName(); + builder.append(Utils.toJVMTypeSignature( + ((Method) target).getReturnType())); + } + targetDesc = builder.toString(); + } + + @Override + public final MethodVisitor visitMethod(int access, String name, + String desc, String signature, + String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, + exceptions); + if (targetDesc.equals(desc) && targetName.equals(name)) { + return new MethodVisitor(Opcodes.ASM5, mv) { + @Override + public void visitLineNumber(int i, Label label) { + super.visitLineNumber(i, label); + lineNumbers.put(label, i); + } + }; + } + return mv; + } + } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -40,25 +40,11 @@ import compiler.jvmci.common.testcases.TestCase; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassVisitor; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.tree.ClassNode; import jdk.test.lib.Asserts; -import jdk.test.lib.Utils; -import java.io.IOException; -import java.lang.reflect.Constructor; import java.lang.reflect.Executable; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.Arrays; -import java.util.HashMap; import java.util.Map; -import java.util.TreeMap; public class GetLineNumberTableTest { public static void main(String[] args) { @@ -80,79 +66,19 @@ } public static long[] getExpectedLineNumbers(Executable aMethod) { - try { - ClassReader cr = new ClassReader(aMethod.getDeclaringClass() - .getName()); - ClassNode cn = new ClassNode(); - cr.accept(cn, ClassReader.EXPAND_FRAMES); - - Map lineNumbers = new HashMap<>(); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - ClassVisitor cv = new ClassVisitorForLabels(cw, lineNumbers, - aMethod); - cr.accept(cv, ClassReader.EXPAND_FRAMES); - - long[] result = null; - if (!lineNumbers.isEmpty()) { - Map labels = new TreeMap<>(); - lineNumbers.forEach((k, v) -> labels.put(k.getOffset(), v)); - - result = new long[2 * labels.size()]; - int i = 0; - for (Integer key : labels.keySet()) { - result[i++] = key.longValue(); - result[i++] = labels.get(key).longValue(); - } + Map bciToLine = CTVMUtilities + .getBciToLineNumber(aMethod); + long[] result = null; + if (!bciToLine.isEmpty()) { + result = new long[2 * bciToLine.size()]; + int i = 0; + for (Integer key : bciToLine.keySet()) { + result[i++] = key.longValue(); + result[i++] = bciToLine.get(key).longValue(); } - // compilerToVM::getLineNumberTable returns null in case empty table - return result; - } catch (IOException e) { - throw new Error("TEST BUG " + e, e); } + // compilerToVM::getLineNumberTable returns null in case empty table + return result; } - private static class ClassVisitorForLabels extends ClassVisitor { - private final Map lineNumbers; - private final String targetName; - private final String targetDesc; - - public ClassVisitorForLabels(ClassWriter cw, Map lines, - Executable target) { - super(Opcodes.ASM5, cw); - this.lineNumbers = lines; - - StringBuilder builder = new StringBuilder("("); - for (Parameter parameter : target.getParameters()) { - builder.append(Utils.toJVMTypeSignature(parameter.getType())); - } - builder.append(")"); - if (target instanceof Constructor) { - targetName = ""; - builder.append("V"); - } else { - targetName = target.getName(); - builder.append(Utils.toJVMTypeSignature( - ((Method) target).getReturnType())); - } - targetDesc = builder.toString(); - } - - @Override - public final MethodVisitor visitMethod(int access, String name, - String desc, String signature, - String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, - exceptions); - if (targetDesc.equals(desc) && targetName.equals(name)) { - return new MethodVisitor(Opcodes.ASM5, mv) { - @Override - public void visitLineNumber(int i, Label label) { - super.visitLineNumber(i, label); - lineNumbers.put(label, i); - } - }; - } - return mv; - } - } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -41,6 +41,8 @@ import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; + +import compiler.jvmci.common.testcases.TestCase; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; @@ -56,22 +58,49 @@ HotSpotResolvedJavaMethod method = CTVMUtilities .getResolvedMethod(aMethod); String className = aMethod.getDeclaringClass().getName(); + String methodName = aMethod.getName().equals(className) + ? "" + : aMethod.getName(); + String fileName = getFileName(className); + Map bciWithLineNumber = CTVMUtilities + .getBciToLineNumber(aMethod); + boolean isNative = Modifier.isNative(aMethod.getModifiers()); + int lineNumber = -1; + for (int bci : bcis) { + StackTraceElement ste = CompilerToVMHelper + .getStackTraceElement(method, bci); + Asserts.assertNotNull(ste, aMethod + " : got null StackTraceElement" + + " at bci " + bci); + Asserts.assertEQ(className, ste.getClassName(), aMethod + + " : unexpected class name"); + Asserts.assertEQ(fileName, ste.getFileName(), aMethod + + " : unexpected filename"); + Asserts.assertEQ(methodName, ste.getMethodName(), aMethod + + " : unexpected method name"); + Asserts.assertEQ(isNative, ste.isNativeMethod(), aMethod + + " : unexpected 'isNative' value"); + if (bciWithLineNumber.size() > 0) { + if (bciWithLineNumber.containsKey(bci)) { + lineNumber = bciWithLineNumber.get(bci); + } + Asserts.assertEQ(lineNumber, ste.getLineNumber(), aMethod + + " : unexpected line number"); + } else { + // native and abstract function + Asserts.assertLT(0, ste.getLineNumber(), + aMethod + " : unexpected line number for abstract " + + "or native method"); + } + } + + } + + private static String getFileName(String className) { int lastDot = className.lastIndexOf('.'); int firstDol = className.contains("$") ? className.indexOf('$') : className.length(); - String fileName = className.substring(lastDot + 1, firstDol) + ".java"; - for (int bci : bcis) { - StackTraceElement ste = CompilerToVMHelper - .getStackTraceElement(method, bci); - Asserts.assertNotNull(ste); - Asserts.assertEQ(ste.getClassName(), className); - Asserts.assertEQ(ste.getFileName(), fileName); - Asserts.assertEQ(ste.getMethodName(), aMethod.getName()); - Asserts.assertEQ(ste.isNativeMethod(), Modifier - .isNative(aMethod.getModifiers())); - } - + return className.substring(lastDot + 1, firstDol) + ".java"; } private static Map createTestCases() { @@ -86,6 +115,13 @@ aMethod = aClass.getDeclaredMethod("dummyEmptyFunction"); bci = new int[] {0}; testCases.put(aMethod, bci); + + aMethod = aClass.getDeclaredMethod("nativeFunction"); + bci = new int[] {0}; + testCases.put(aMethod, bci); + + TestCase.getAllExecutables() + .forEach(c -> testCases.put(c, new int[] {0})); } catch (NoSuchMethodException e) { throw new Error("TEST BUG : test method not found", e); } @@ -102,5 +138,7 @@ } public void dummyEmptyFunction() {} + + public native void nativeFunction(); } } diff -r 3c271ee8fb98 -r 57d99d1614e0 hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java --- a/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java Wed Nov 25 01:17:28 2015 +0300 +++ b/hotspot/test/compiler/jvmci/compilerToVM/IsMatureTest.java Wed Nov 25 00:40:04 2015 +0100 @@ -35,9 +35,11 @@ * -XX:+WhiteBoxAPI -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI * compiler.jvmci.compilerToVM.IsMatureTest */ + package compiler.jvmci.compilerToVM; import compiler.jvmci.common.testcases.SimpleClass; +import compiler.whitebox.CompilerWhiteBoxTest; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.test.lib.Asserts; import sun.hotspot.WhiteBox; @@ -46,6 +48,10 @@ public class IsMatureTest { private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final boolean IS_XCOMP + = System.getProperty("java.vm.info").contains("compiled mode"); + private static final boolean TIERED + = WB.getBooleanVMFlag("TieredCompilation"); public static void main(String[] args) throws Exception { new IsMatureTest().test(); @@ -54,23 +60,21 @@ public void test() throws Exception { SimpleClass sclass = new SimpleClass(); Executable method = SimpleClass.class.getDeclaredMethod("testMethod"); - long metaspaceMethodData = WB.getMethodData(method); - Asserts.assertEQ(metaspaceMethodData, 0L, "MDO should be null for " - + "never invoked method"); - boolean isMature = CompilerToVMHelper.isMature(metaspaceMethodData); - Asserts.assertFalse(isMature, "null MDO can't be mature"); - for (int i = 0; i < 1000; i++) { + long methodData = WB.getMethodData(method); + boolean isMature = CompilerToVMHelper.isMature(methodData); + Asserts.assertEQ(methodData, 0L, + "Never invoked method can't have method data"); + Asserts.assertFalse(isMature, "Never invoked method can't be mature"); + for (int i = 0; i < CompilerWhiteBoxTest.THRESHOLD; i++) { sclass.testMethod(); } - // warmed up, mdo should be ready for now - metaspaceMethodData = WB.getMethodData(method); - Asserts.assertNE(metaspaceMethodData, 0L, - "MDO should be available after 1000 calls"); - for (int i = 0; i < 100_000; i++) { - sclass.testMethod(); - } - isMature = CompilerToVMHelper.isMature(metaspaceMethodData); - Asserts.assertTrue(isMature, - "a 100_000 times invoked method should be mature"); + methodData = WB.getMethodData(method); + isMature = CompilerToVMHelper.isMature(methodData); + Asserts.assertNE(methodData, 0L, + "Multiple times invoked method should have method data"); + /* a method is not mature for -Xcomp and -Tiered, + see NonTieredCompPolicy::is_mature */ + Asserts.assertEQ(isMature, !(IS_XCOMP && !TIERED), + "Unexpected isMature state for multiple times invoked method"); } }