--- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java 2016-05-11 09:26:14.295431539 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java 2016-05-11 09:26:14.052430751 +0200 @@ -351,6 +351,18 @@ } /** + * Notify on completion of a bootstrap. + * + * Called from the VM. + */ + @SuppressWarnings({"unused"}) + private void bootstrapFinished() throws Exception { + for (HotSpotVMEventListener vmEventListener : vmEventListeners) { + vmEventListener.notifyBootstrapFinished(); + } + } + + /** * Notify on successful install into the CodeCache. * * @param hotSpotCodeCacheProvider --- old/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/services/HotSpotVMEventListener.java 2016-05-11 09:26:15.403435135 +0200 +++ new/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/services/HotSpotVMEventListener.java 2016-05-11 09:26:15.182434417 +0200 @@ -75,6 +75,12 @@ } /** + * Notify on completion of a bootstrap. + */ + public void notifyBootstrapFinished() { + } + + /** * Create a custom {@link JVMCIMetaAccessContext} to be used for managing the lifetime of loaded * metadata. It a custom one isn't created then the default implementation will be a single * context with globally shared instances of {@link ResolvedJavaType} that are never released. --- old/src/share/vm/classfile/vmSymbols.hpp 2016-05-11 09:26:17.128440732 +0200 +++ new/src/share/vm/classfile/vmSymbols.hpp 2016-05-11 09:26:16.893439969 +0200 @@ -358,6 +358,7 @@ template(nthreads_name, "nthreads") \ template(ngroups_name, "ngroups") \ template(shutdown_method_name, "shutdown") \ + template(bootstrapFinished_method_name, "bootstrapFinished") \ template(finalize_method_name, "finalize") \ template(reference_lock_name, "lock") \ template(reference_discovered_name, "discovered") \ --- old/src/share/vm/jvmci/jvmciCompiler.cpp 2016-05-11 09:26:18.374444775 +0200 +++ new/src/share/vm/jvmci/jvmciCompiler.cpp 2016-05-11 09:26:18.187444168 +0200 @@ -39,6 +39,7 @@ JVMCICompiler::JVMCICompiler() : AbstractCompiler(jvmci) { _bootstrapping = false; + _bootstrap_compilation_request_handled = false; _methods_compiled = 0; assert(_instance == NULL, "only one instance allowed"); _instance = this; @@ -57,7 +58,7 @@ CompilationPolicy::completed_vm_startup(); } -void JVMCICompiler::bootstrap() { +void JVMCICompiler::bootstrap(TRAPS) { if (Arguments::mode() == Arguments::_int) { // Nothing to do in -Xint mode return; @@ -68,7 +69,6 @@ FlagSetting ctwOff(CompileTheWorld, false); #endif - JavaThread* THREAD = JavaThread::current(); _bootstrapping = true; ResourceMark rm; HandleMark hm; @@ -97,7 +97,7 @@ do { os::sleep(THREAD, 100, true); qsize = CompileBroker::queue_size(CompLevel_full_optimization); - } while (first_round && qsize == 0); + } while (!_bootstrap_compilation_request_handled && first_round && qsize == 0); first_round = false; if (PrintBootstrap) { while (z < (_methods_compiled / 100)) { @@ -111,6 +111,7 @@ tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled); } _bootstrapping = false; + JVMCIRuntime::bootstrap_finished(CHECK); } #define CHECK_ABORT THREAD); \ @@ -187,6 +188,9 @@ assert(false, "JVMCICompiler.compileMethod should always return non-null"); } } + if (_bootstrapping) { + _bootstrap_compilation_request_handled = true; + } } /** --- old/src/share/vm/jvmci/jvmciCompiler.hpp 2016-05-11 09:26:19.044446949 +0200 +++ new/src/share/vm/jvmci/jvmciCompiler.hpp 2016-05-11 09:26:18.866446372 +0200 @@ -33,6 +33,11 @@ bool _bootstrapping; /** + * True if we have seen a bootstrap compilation request. + */ + volatile bool _bootstrap_compilation_request_handled; + + /** * Number of methods successfully compiled by a call to * JVMCICompiler::compile_method(). */ @@ -68,7 +73,7 @@ // Initialization virtual void initialize(); - void bootstrap(); + void bootstrap(TRAPS); // Compilation entry point for methods virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive); --- old/src/share/vm/jvmci/jvmciRuntime.cpp 2016-05-11 09:26:20.113450418 +0200 +++ new/src/share/vm/jvmci/jvmciRuntime.cpp 2016-05-11 09:26:19.841449536 +0200 @@ -803,6 +803,15 @@ } } +void JVMCIRuntime::bootstrap_finished(TRAPS) { + HandleMark hm(THREAD); + Handle receiver = get_HotSpotJVMCIRuntime(CHECK); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(receiver); + JavaCalls::call_special(&result, receiver->klass(), vmSymbols::bootstrapFinished_method_name(), vmSymbols::void_method_signature(), &args, CHECK); +} + bool JVMCIRuntime::treat_as_trivial(Method* method) { if (_HotSpotJVMCIRuntime_initialized) { for (int i = 0; i < _trivial_prefixes_count; i++) { --- old/src/share/vm/jvmci/jvmciRuntime.hpp 2016-05-11 09:26:21.463454799 +0200 +++ new/src/share/vm/jvmci/jvmciRuntime.hpp 2016-05-11 09:26:20.930453069 +0200 @@ -120,6 +120,8 @@ static void shutdown(TRAPS); + static void bootstrap_finished(TRAPS); + static bool shutdown_called() { return _shutdown_called; } --- old/src/share/vm/prims/jni.cpp 2016-05-11 09:26:22.521458232 +0200 +++ new/src/share/vm/prims/jni.cpp 2016-05-11 09:26:22.259457382 +0200 @@ -3988,7 +3988,11 @@ if (BootstrapJVMCI) { JavaThread* THREAD = thread; JVMCICompiler* compiler = JVMCICompiler::instance(CATCH); - compiler->bootstrap(); + compiler->bootstrap(THREAD); + if (HAS_PENDING_EXCEPTION) { + HandleMark hm; + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } } } } --- old/test/compiler/jvmci/common/services/jdk.vm.ci.hotspot.HotSpotVMEventListener 2016-05-11 09:26:23.749462217 +0200 +++ /dev/null 2016-04-27 14:37:27.957220952 +0200 @@ -1 +0,0 @@ -compiler.jvmci.common.JVMCIHelpers$EmptyVMEventListener --- /dev/null 2016-04-27 14:37:27.957220952 +0200 +++ new/test/compiler/jvmci/common/services/jdk.vm.ci.hotspot.services.HotSpotVMEventListener 2016-05-11 09:26:23.299460756 +0200 @@ -0,0 +1 @@ +compiler.jvmci.common.JVMCIHelpers$EmptyVMEventListener --- old/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.JVMCICompilerFactory 2016-05-11 09:26:24.579464910 +0200 +++ /dev/null 2016-04-27 14:37:27.957220952 +0200 @@ -1 +0,0 @@ -compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory --- /dev/null 2016-04-27 14:37:27.957220952 +0200 +++ new/test/compiler/jvmci/common/services/jdk.vm.ci.runtime.services.JVMCICompilerFactory 2016-05-11 09:26:24.195463664 +0200 @@ -0,0 +1 @@ +compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory --- /dev/null 2016-04-27 14:37:27.957220952 +0200 +++ new/test/compiler/jvmci/events/JvmciNotifyBootstrapFinishedEventTest.config 2016-05-11 09:26:25.038466399 +0200 @@ -0,0 +1 @@ +compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest --- /dev/null 2016-04-27 14:37:27.957220952 +0200 +++ new/test/compiler/jvmci/events/JvmciNotifyBootstrapFinishedEventTest.java 2016-05-11 09:26:26.257470355 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, 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 8156034 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library / /testlibrary + * @library ../common/patches + * @modules java.base/jdk.internal.org.objectweb.asm + * java.base/jdk.internal.org.objectweb.asm.tree + * jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper + * @build compiler.jvmci.common.JVMCIHelpers + * compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest + * @run main jdk.test.lib.FileInstaller ../common/services/ ./META-INF/services/ + * @run main jdk.test.lib.FileInstaller ./JvmciNotifyBootstrapFinishedEventTest.config + * ./META-INF/services/jdk.vm.ci.hotspot.services.HotSpotVMEventListener + * @run main ClassFileInstaller + * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler + * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory + * compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest + * jdk.test.lib.Asserts + * jdk.test.lib.Utils + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. + * -XX:+UseJVMCICompiler -XX:-BootstrapJVMCI + * -Dcompiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest.bootstrap=false + * compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI + * -Djvmci.Compiler=EmptyCompiler -Xbootclasspath/a:. + * -XX:+UseJVMCICompiler -XX:+BootstrapJVMCI + * -Dcompiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest.bootstrap=true + * compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest + */ + +package compiler.jvmci.events; + +import jdk.test.lib.Asserts; +import jdk.vm.ci.hotspot.services.HotSpotVMEventListener; + +public class JvmciNotifyBootstrapFinishedEventTest extends HotSpotVMEventListener { + private static final boolean BOOTSTRAP = Boolean + .getBoolean("compiler.jvmci.events.JvmciNotifyBootstrapFinishedEventTest.bootstrap"); + private static volatile int gotBoostrapNotification = 0; + + public static void main(String args[]) { + if (BOOTSTRAP) { + Asserts.assertEQ(gotBoostrapNotification, 1, "Did not receive expected number of bootstrap events"); + } else { + Asserts.assertEQ(gotBoostrapNotification, 0, "Got unexpected bootstrap event"); + } + } + + @Override + public void notifyBootstrapFinished() { + gotBoostrapNotification++; + } +}