# HG changeset patch # User Doug Simon # Date 1462802896 -7200 # Node ID 24505bf61633a964563b193e6d8f369d1f9bf213 # Parent b11f345e4af4f7acea5e7e19fb6370408bfe587b allow JVMCI compiler to change the compilation policy for a method (JDK-8152311) diff -r b11f345e4af4 -r 24505bf61633 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java --- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Mon May 09 11:31:54 2016 +0200 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Mon May 09 16:08:16 2016 +0200 @@ -42,6 +42,7 @@ import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.services.HotSpotVMEventListener; import jdk.vm.ci.inittimer.InitTimer; import jdk.vm.ci.inittimer.SuppressFBWarnings; @@ -52,6 +53,7 @@ import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCIBackend; import jdk.vm.ci.runtime.JVMCICompiler; +import jdk.vm.ci.runtime.services.JVMCICompilerFactory; import jdk.vm.ci.services.Services; import sun.misc.VM; @@ -204,13 +206,25 @@ protected final HotSpotVMConfig config; private final JVMCIBackend hostBackend; + private final JVMCICompilerFactory compilerFactory; + private final HotSpotJVMCICompilerFactory hsCompilerFactory; private volatile JVMCICompiler compiler; protected final JVMCIMetaAccessContext metaAccessContext; + /** + * Stores the result of {@link HotSpotJVMCICompilerFactory#getCompilationLevelAdjustment} so + * that it can be read from the VM. + */ + @SuppressWarnings("unused") private final int compilationLevelAdjustment; + private final Map, JVMCIBackend> backends = new HashMap<>(); private final Iterable vmEventListeners; + /** + * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can + * be read from the VM. + */ @SuppressWarnings("unused") private final String[] trivialPrefixes; @SuppressWarnings("try") @@ -259,7 +273,16 @@ printConfig(config, compilerToVm); } - trivialPrefixes = HotSpotJVMCICompilerConfig.getCompilerFactory().getTrivialPrefixes(); + compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(); + if (compilerFactory instanceof HotSpotJVMCICompilerFactory) { + hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory; + trivialPrefixes = hsCompilerFactory.getTrivialPrefixes(); + compilationLevelAdjustment = hsCompilerFactory.getCompilationLevelAdjustment(config); + } else { + hsCompilerFactory = null; + trivialPrefixes = null; + compilationLevelAdjustment = 0; + } } private JVMCIBackend registerBackend(JVMCIBackend backend) { @@ -289,7 +312,7 @@ if (compiler == null) { synchronized (this) { if (compiler == null) { - compiler = HotSpotJVMCICompilerConfig.getCompilerFactory().createCompiler(this); + compiler = compilerFactory.createCompiler(this); } } } @@ -332,6 +355,14 @@ * Called from the VM. */ @SuppressWarnings({"unused"}) + private int adjustCompilationLevel(Class declaringClass, String name, String signature, boolean isOsr, int level) { + return hsCompilerFactory.adjustCompilationLevel(config, declaringClass, name, signature, isOsr, level); + } + + /** + * Called from the VM. + */ + @SuppressWarnings({"unused"}) private CompilationRequestResult compileMethod(HotSpotResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id) { CompilationRequestResult result = getCompiler().compileMethod(new HotSpotCompilationRequest(method, entryBCI, jvmciEnv, id)); assert result != null : "compileMethod must always return something"; diff -r b11f345e4af4 -r 24505bf61633 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java --- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Mon May 09 11:31:54 2016 +0200 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Mon May 09 16:08:16 2016 +0200 @@ -1264,8 +1264,16 @@ @HotSpotVMField(name = "nmethod::_verified_entry_point", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodEntryOffset; @HotSpotVMField(name = "nmethod::_comp_level", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int nmethodCompLevelOffset; + @HotSpotVMConstant(name = "CompLevel_none") @Stable public int compilationLevelNone; + @HotSpotVMConstant(name = "CompLevel_simple") @Stable public int compilationLevelSimple; + @HotSpotVMConstant(name = "CompLevel_limited_profile") @Stable public int compilationLevelLimitedProfile; + @HotSpotVMConstant(name = "CompLevel_full_profile") @Stable public int compilationLevelFullProfile; @HotSpotVMConstant(name = "CompLevel_full_optimization") @Stable public int compilationLevelFullOptimization; + @HotSpotVMConstant(name = "JVMCIRuntime::none") @Stable public int compLevelAdjustmentNone; + @HotSpotVMConstant(name = "JVMCIRuntime::by_holder") @Stable public int compLevelAdjustmentByHolder; + @HotSpotVMConstant(name = "JVMCIRuntime::by_full_signature") @Stable public int compLevelAdjustmentByFullSignature; + @HotSpotVMType(name = "BasicLock", get = HotSpotVMType.Type.SIZE) @Stable public int basicLockSize; @HotSpotVMField(name = "BasicLock::_displaced_header", type = "markOop", get = HotSpotVMField.Type.OFFSET) @Stable public int basicLockDisplacedHeaderOffset; diff -r b11f345e4af4 -r 24505bf61633 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/services/HotSpotJVMCICompilerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/services/HotSpotJVMCICompilerFactory.java Mon May 09 16:08:16 2016 +0200 @@ -0,0 +1,76 @@ +/* + * 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. + */ +package jdk.vm.ci.hotspot.services; + +import jdk.vm.ci.hotspot.HotSpotVMConfig; +import jdk.vm.ci.runtime.services.JVMCICompilerFactory; + +/** + * HotSpot extensions to {@link JVMCICompilerFactory}. + */ +public abstract class HotSpotJVMCICompilerFactory extends JVMCICompilerFactory { + + /** + * Gets 0 or more prefixes identifying classes that should by compiled by C1 in simple mode + * (i.e., {@code CompLevel_simple}) when HotSpot is running with tiered compilation. The + * prefixes should be class or package names using "/" as the separator, e.g. "jdk/vm/ci". + * + * @return 0 or more Strings identifying packages that should by compiled by the first tier only + * or null if no redirection to C1 should be performed. + */ + public String[] getTrivialPrefixes() { + return null; + } + + /** + * Determines if this object may want to adjust the compilation level for a method that is being + * scheduled by the VM for compilation. The legal return values and their meanings are: + *
    + *
  • 0 - no adjustment
  • + *
  • 1 - adjust based on declaring class of method
  • + *
  • 2 - adjust based on declaring class, name and signature of method
  • + *
+ */ + public int getCompilationLevelAdjustment(HotSpotVMConfig config) { + return config.compLevelAdjustmentNone; + } + + /** + * Potentially modifies the compilation level currently selected by the VM compilation policy + * for a method. + * + * @param config object for reading HotSpot {@code CompLevel} enum values + * @param declaringClass the class in which the method is declared + * @param name the name of the method or {@code null} depending on the value that was returned + * by {@link #getCompilationLevelAdjustment(HotSpotVMConfig)} + * @param signature the signature of the method or {@code null} depending on the value that was + * returned by {@link #getCompilationLevelAdjustment(HotSpotVMConfig)} + * @param isOsr specifies if the compilation being scheduled in an OSR compilation + * @param level the compilation level currently selected by the VM compilation policy + * @return the compilation level to use for the compilation being scheduled (must be a valid + * {@code CompLevel} enum value) + */ + public int adjustCompilationLevel(HotSpotVMConfig config, Class declaringClass, String name, String signature, boolean isOsr, int level) { + throw new InternalError("Should not reach here"); + } +} diff -r b11f345e4af4 -r 24505bf61633 jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/services/JVMCICompilerFactory.java --- a/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/services/JVMCICompilerFactory.java Mon May 09 11:31:54 2016 +0200 +++ b/jvmci/jdk.vm.ci.runtime/src/jdk/vm/ci/runtime/services/JVMCICompilerFactory.java Mon May 09 16:08:16 2016 +0200 @@ -69,17 +69,4 @@ * Create a new instance of a {@link JVMCICompiler}. */ public abstract JVMCICompiler createCompiler(JVMCIRuntime runtime); - - /** - * In a tiered system it might be advantageous for startup to keep the JVMCI compiler from - * compiling itself so provide a hook to request that certain packages are compiled only by an - * optimizing first tier. The prefixes should class or package names using / as the separator, - * i.e. jdk/vm/ci for instance. - * - * @return 0 or more Strings identifying packages that should by compiled by the first tier - * only. - */ - public String[] getTrivialPrefixes() { - return null; - } } diff -r b11f345e4af4 -r 24505bf61633 mx.jvmci/mx_jvmci.py --- a/mx.jvmci/mx_jvmci.py Mon May 09 11:31:54 2016 +0200 +++ b/mx.jvmci/mx_jvmci.py Mon May 09 16:08:16 2016 +0200 @@ -594,7 +594,7 @@ fp.write('SOURCE=" ' + ' '.join((k + ":" + v for k, v in versions.iteritems())) + '"' + os.linesep) mx.logv("Updating " + releaseFile) except BaseException as e: - mx.warn("Exception " + str(e) + " while updaing release file") + mx.warn("Exception " + str(e) + " while updating release file") fp.write(line) else: fp.write(line) diff -r b11f345e4af4 -r 24505bf61633 src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon May 09 11:31:54 2016 +0200 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon May 09 16:08:16 2016 +0200 @@ -2650,7 +2650,7 @@ { BLOCK_COMMENT("assert primitive array {"); Label L; - __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); + __ cmpl(rax_lh, ((unsigned)Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); __ jcc(Assembler::greaterEqual, L); __ stop("must be a primitive array"); __ bind(L); diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/jvmciCompiler.hpp --- a/src/share/vm/jvmci/jvmciCompiler.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/jvmciCompiler.hpp Mon May 09 16:08:16 2016 +0200 @@ -68,8 +68,14 @@ #ifdef COMPILERJVMCI + /** + * Initialize the compile queue with the methods in java.lang.Object and + * then wait until the queue is empty. + */ void bootstrap(); - + + bool is_bootstrapping() const { return _bootstrapping; } + // Compilation entry point for methods virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci); diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/jvmciJavaClasses.hpp --- a/src/share/vm/jvmci/jvmciJavaClasses.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/jvmciJavaClasses.hpp Mon May 09 16:08:16 2016 +0200 @@ -32,7 +32,7 @@ static void compute_offsets(TRAPS); }; -/* This macro defines the structure of the CompilationResult - classes. +/* This macro defines the structure of the JVMCI classes accessed from VM code. * It will generate classes with accessors similar to javaClasses.hpp, but with specializations for oops, Handles and jni handles. * * The public interface of these classes will look like this: @@ -280,6 +280,7 @@ end_class \ start_class(HotSpotJVMCIRuntime) \ objArrayOop_field(HotSpotJVMCIRuntime, trivialPrefixes, "[Ljava/lang/String;") \ + int_field(HotSpotJVMCIRuntime, compilationLevelAdjustment) \ end_class \ /* end*/ diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/jvmciRuntime.cpp --- a/src/share/vm/jvmci/jvmciRuntime.cpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/jvmciRuntime.cpp Mon May 09 16:08:16 2016 +0200 @@ -49,6 +49,7 @@ bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false; int JVMCIRuntime::_trivial_prefixes_count = 0; char** JVMCIRuntime::_trivial_prefixes = NULL; +JVMCIRuntime::CompLevelAdjustment JVMCIRuntime::_comp_level_adjustment = JVMCIRuntime::none; bool JVMCIRuntime::_shutdown_called = false; BasicType JVMCIRuntime::kindToBasicType(jchar ch, TRAPS) { @@ -662,6 +663,11 @@ _trivial_prefixes = prefixes; _trivial_prefixes_count = trivial_prefixes->length(); } + int adjustment = HotSpotJVMCIRuntime::compilationLevelAdjustment(result); + assert(adjustment >= JVMCIRuntime::none && + adjustment <= JVMCIRuntime::by_full_signature, + "compilation level adjustment out of bounds"); + _comp_level_adjustment = (CompLevelAdjustment) adjustment; _HotSpotJVMCIRuntime_initialized = true; _HotSpotJVMCIRuntime_instance = JNIHandles::make_global(result()); } @@ -927,6 +933,88 @@ return false; } +CompLevel JVMCIRuntime::adjust_comp_level(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread) { + if (!thread->adjusting_comp_level()) { + thread->set_adjusting_comp_level(true); + level = adjust_comp_level_inner(method, is_osr, level, thread); + thread->set_adjusting_comp_level(false); + } + return level; +} + +CompLevel JVMCIRuntime::adjust_comp_level_inner(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread) { +#ifdef COMPILERJVMCI + JVMCICompiler* compiler = JVMCICompiler::instance(thread); + if (compiler != NULL && compiler->is_bootstrapping()) { + return level; + } +#endif + if (!is_HotSpotJVMCIRuntime_initialized() || !_comp_level_adjustment) { + // JVMCI cannot participate in compilation scheduling until + // JVMCI is initialized and indicates it wants to participate. + return level; + } + +#define CHECK_RETURN THREAD); \ +if (HAS_PENDING_EXCEPTION) { \ + Handle exception(THREAD, PENDING_EXCEPTION); \ + CLEAR_PENDING_EXCEPTION; \ +\ + java_lang_Throwable::print(exception, tty); \ + tty->cr(); \ + java_lang_Throwable::print_stack_trace(exception(), tty); \ + if (HAS_PENDING_EXCEPTION) { \ + CLEAR_PENDING_EXCEPTION; \ + } \ + return level; \ +} \ +(void)(0 + + Thread* THREAD = thread; + HandleMark hm; + Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_RETURN); + Handle name; + Handle sig; + if (_comp_level_adjustment == JVMCIRuntime::by_full_signature) { + name = java_lang_String::create_from_symbol(method->name(), CHECK_RETURN); + sig = java_lang_String::create_from_symbol(method->signature(), CHECK_RETURN); + } else { + name = Handle(); + sig = Handle(); + } + + JavaValue result(T_INT); + JavaCallArguments args; + args.push_oop(receiver); + args.push_oop(method->method_holder()->java_mirror()); + args.push_oop(name()); + args.push_oop(sig()); + args.push_int(is_osr); + args.push_int(level); + JavaCalls::call_special(&result, receiver->klass(), vmSymbols::adjustCompilationLevel_name(), + vmSymbols::adjustCompilationLevel_signature(), &args, CHECK_RETURN); + + // An uncaught exception was thrown. Generally these + // should be handled by the Java code in some useful way but if they leak + // through to here report them instead of dying or silently ignoring them. + if (HAS_PENDING_EXCEPTION) { + Handle throwable = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + + java_lang_Throwable::print(throwable, tty); + tty->cr(); + java_lang_Throwable::print_stack_trace(throwable(), tty); + return level; + } + int comp_level = result.get_jint(); + if (comp_level < CompLevel_none || comp_level > CompLevel_full_optimization) { + assert(false, "compilation level out of bounds"); + return level; + } + return (CompLevel) comp_level; +#undef CHECK_RETURN +} + void JVMCIRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { Thread* THREAD = Thread::current(); CLEAR_PENDING_EXCEPTION; diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/jvmciRuntime.hpp --- a/src/share/vm/jvmci/jvmciRuntime.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/jvmciRuntime.hpp Mon May 09 16:08:16 2016 +0200 @@ -68,6 +68,16 @@ }; class JVMCIRuntime: public AllStatic { + public: + // Constants describing whether JVMCI wants to be able to adjust the compilation + // level selected for a method by the VM compilation policy and if so, based on + // what information about the method being schedule for compilation. + enum CompLevelAdjustment { + none = 0, // no adjustment + by_holder = 1, // adjust based on declaring class of method + by_full_signature = 2 // adjust based on declaring class, name and signature of method + }; + private: static jobject _HotSpotJVMCIRuntime_instance; static bool _HotSpotJVMCIRuntime_initialized; @@ -75,6 +85,8 @@ static int _trivial_prefixes_count; static char** _trivial_prefixes; + static CompLevelAdjustment _comp_level_adjustment; + static bool _shutdown_called; /** @@ -84,6 +96,8 @@ */ static Handle create_Service(const char* name, TRAPS); + static CompLevel adjust_comp_level_inner(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread); + public: /** * Parses *.properties files in jre/lib/jvmci/ and adds the properties to plist. @@ -136,6 +150,18 @@ static bool treat_as_trivial(Method* method); /** + * Lets JVMCI modify the compilation level currently selected for a method by + * the VM compilation policy. + * + * @param method the method being scheduled for compilation + * @param is_osr specifies if the compilation is an OSR compilation + * @param level the compilation level currently selected by the VM compilation policy + * @param thread the current thread + * @return the compilation level to use for the compilation + */ + static CompLevel adjust_comp_level(methodHandle method, bool is_osr, CompLevel level, JavaThread* thread); + + /** * Given an interface representing a JVMCI service, gets an array of objects, one per * known implementation of the service. */ diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/vmStructs_jvmci.hpp --- a/src/share/vm/jvmci/vmStructs_jvmci.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/vmStructs_jvmci.hpp Mon May 09 16:08:16 2016 +0200 @@ -55,6 +55,9 @@ declare_constant(JVMCIEnv::dependencies_invalid) \ declare_constant(JVMCIEnv::cache_full) \ declare_constant(JVMCIEnv::code_too_large) \ + declare_constant(JVMCIRuntime::none) \ + declare_constant(JVMCIRuntime::by_holder) \ + declare_constant(JVMCIRuntime::by_full_signature) \ \ declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \ declare_preprocessor_constant("JVM_RECOGNIZED_FIELD_MODIFIERS", JVM_RECOGNIZED_FIELD_MODIFIERS) \ diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/jvmci/vmSymbols_jvmci.hpp --- a/src/share/vm/jvmci/vmSymbols_jvmci.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/jvmci/vmSymbols_jvmci.hpp Mon May 09 16:08:16 2016 +0200 @@ -86,6 +86,8 @@ template(jdk_vm_ci_code_site_Site, "jdk/vm/ci/code/site/Site") \ template(jdk_vm_ci_code_site_InfopointReason, "jdk/vm/ci/code/site/InfopointReason") \ template(jdk_vm_ci_common_JVMCIError, "jdk/vm/ci/common/JVMCIError") \ + template(adjustCompilationLevel_name, "adjustCompilationLevel") \ + template(adjustCompilationLevel_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;ZI)I") \ template(compileMethod_name, "compileMethod") \ template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/code/CompilationRequestResult;") \ template(fromMetaspace_name, "fromMetaspace") \ diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/advancedThresholdPolicy.cpp --- a/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon May 09 16:08:16 2016 +0200 @@ -25,6 +25,9 @@ #include "precompiled.hpp" #include "runtime/advancedThresholdPolicy.hpp" #include "runtime/simpleThresholdPolicy.inline.hpp" +#ifdef COMPILERJVMCI +#include "jvmci/jvmciRuntime.hpp" +#endif #ifdef TIERED // Print an event. @@ -433,7 +436,7 @@ } // Determine if a method should be compiled with a normal entry point at a different level. -CompLevel AdvancedThresholdPolicy::call_event(Method* method, CompLevel cur_level) { +CompLevel AdvancedThresholdPolicy::call_event(Method* method, CompLevel cur_level, JavaThread * thread) { CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(), common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true)); CompLevel next_level = common(&AdvancedThresholdPolicy::call_predicate, method, cur_level); @@ -450,11 +453,12 @@ } else { next_level = MAX2(osr_level, next_level); } + COMPILERJVMCI_PRESENT(next_level = JVMCIRuntime::adjust_comp_level(method, false, next_level, thread);) return next_level; } // Determine if we should do an OSR compilation of a given method. -CompLevel AdvancedThresholdPolicy::loop_event(Method* method, CompLevel cur_level) { +CompLevel AdvancedThresholdPolicy::loop_event(Method* method, CompLevel cur_level, JavaThread * thread) { CompLevel next_level = common(&AdvancedThresholdPolicy::loop_predicate, method, cur_level, true); if (cur_level == CompLevel_none) { // If there is a live OSR method that means that we deopted to the interpreter @@ -464,6 +468,7 @@ return osr_level; } } + COMPILERJVMCI_PRESENT(next_level = JVMCIRuntime::adjust_comp_level(method, true, next_level, thread);) return next_level; } @@ -481,7 +486,7 @@ create_mdo(mh, thread); } if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { - CompLevel next_level = call_event(mh(), level); + CompLevel next_level = call_event(mh(), level, thread); if (next_level != level) { compile(mh, InvocationEntryBci, next_level, thread); } @@ -501,7 +506,7 @@ } if (is_compilation_enabled()) { - CompLevel next_osr_level = loop_event(imh(), level); + CompLevel next_osr_level = loop_event(imh(), level, thread); CompLevel max_osr_level = (CompLevel)imh->highest_osr_comp_level(); // At the very least compile the OSR version if (!CompileBroker::compilation_is_in_queue(imh) && (next_osr_level != level)) { @@ -514,7 +519,7 @@ if (mh() != imh()) { // If there is an enclosing method guarantee(nm != NULL, "Should have nmethod here"); cur_level = comp_level(mh()); - next_level = call_event(mh(), cur_level); + next_level = call_event(mh(), cur_level, thread); if (max_osr_level == CompLevel_full_optimization) { // The inlinee OSRed to full opt, we need to modify the enclosing method to avoid deopts @@ -549,7 +554,7 @@ } } else { cur_level = comp_level(imh()); - next_level = call_event(imh(), cur_level); + next_level = call_event(imh(), cur_level, thread); if (!CompileBroker::compilation_is_in_queue(imh) && (next_level != cur_level)) { compile(imh, InvocationEntryBci, next_level, thread); } diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/advancedThresholdPolicy.hpp --- a/src/share/vm/runtime/advancedThresholdPolicy.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/advancedThresholdPolicy.hpp Mon May 09 16:08:16 2016 +0200 @@ -172,10 +172,10 @@ // Transition functions. // call_event determines if a method should be compiled at a different // level with a regular invocation entry. - CompLevel call_event(Method* method, CompLevel cur_level); + CompLevel call_event(Method* method, CompLevel cur_level, JavaThread * thread); // loop_event checks if a method should be OSR compiled at a different // level. - CompLevel loop_event(Method* method, CompLevel cur_level); + CompLevel loop_event(Method* method, CompLevel cur_level, JavaThread * thread); // Has a method been long around? // We don't remove old methods from the compile queue even if they have // very low activity (see select_task()). diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/simpleThresholdPolicy.cpp --- a/src/share/vm/runtime/simpleThresholdPolicy.cpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/simpleThresholdPolicy.cpp Mon May 09 16:08:16 2016 +0200 @@ -29,6 +29,9 @@ #include "runtime/simpleThresholdPolicy.hpp" #include "runtime/simpleThresholdPolicy.inline.hpp" #include "code/scopeDesc.hpp" +#ifdef COMPILERJVMCI +#include "jvmci/jvmciRuntime.hpp" +#endif void SimpleThresholdPolicy::print_counters(const char* prefix, methodHandle mh) { @@ -340,7 +343,7 @@ } // Determine if a method should be compiled with a normal entry point at a different level. -CompLevel SimpleThresholdPolicy::call_event(Method* method, CompLevel cur_level) { +CompLevel SimpleThresholdPolicy::call_event(Method* method, CompLevel cur_level, JavaThread* thread) { CompLevel osr_level = MIN2((CompLevel) method->highest_osr_comp_level(), common(&SimpleThresholdPolicy::loop_predicate, method, cur_level)); CompLevel next_level = common(&SimpleThresholdPolicy::call_predicate, method, cur_level); @@ -357,12 +360,12 @@ } else { next_level = MAX2(osr_level, next_level); } - + COMPILERJVMCI_PRESENT(next_level = JVMCIRuntime::adjust_comp_level(method, false, next_level, thread);) return next_level; } // Determine if we should do an OSR compilation of a given method. -CompLevel SimpleThresholdPolicy::loop_event(Method* method, CompLevel cur_level) { +CompLevel SimpleThresholdPolicy::loop_event(Method* method, CompLevel cur_level, JavaThread* thread) { CompLevel next_level = common(&SimpleThresholdPolicy::loop_predicate, method, cur_level); if (cur_level == CompLevel_none) { // If there is a live OSR method that means that we deopted to the interpreter @@ -372,6 +375,7 @@ return osr_level; } } + COMPILERJVMCI_PRESENT(next_level = JVMCIRuntime::adjust_comp_level(method, true, next_level, thread);) return next_level; } @@ -380,7 +384,7 @@ void SimpleThresholdPolicy::method_invocation_event(methodHandle mh, methodHandle imh, CompLevel level, nmethod* nm, JavaThread* thread) { if (is_compilation_enabled() && !CompileBroker::compilation_is_in_queue(mh)) { - CompLevel next_level = call_event(mh(), level); + CompLevel next_level = call_event(mh(), level, thread); if (next_level != level) { compile(mh, InvocationEntryBci, next_level, thread); } @@ -396,8 +400,8 @@ // Use loop event as an opportunity to also check there's been // enough calls. CompLevel cur_level = comp_level(mh()); - CompLevel next_level = call_event(mh(), cur_level); - CompLevel next_osr_level = loop_event(mh(), level); + CompLevel next_level = call_event(mh(), cur_level, thread); + CompLevel next_osr_level = loop_event(mh(), level, thread); next_level = MAX2(next_level, next_osr_level < CompLevel_full_optimization ? next_osr_level : cur_level); diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/simpleThresholdPolicy.hpp --- a/src/share/vm/runtime/simpleThresholdPolicy.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/simpleThresholdPolicy.hpp Mon May 09 16:08:16 2016 +0200 @@ -51,10 +51,10 @@ // Transition functions. // call_event determines if a method should be compiled at a different // level with a regular invocation entry. - CompLevel call_event(Method* method, CompLevel cur_level); + CompLevel call_event(Method* method, CompLevel cur_level, JavaThread* thread); // loop_event checks if a method should be OSR compiled at a different // level. - CompLevel loop_event(Method* method, CompLevel cur_level); + CompLevel loop_event(Method* method, CompLevel cur_level, JavaThread* thread); void print_counters(const char* prefix, methodHandle mh); protected: int c1_count() const { return _c1_count; } diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/thread.cpp Mon May 09 16:08:16 2016 +0200 @@ -1487,6 +1487,7 @@ _pending_deoptimization = -1; _pending_failed_speculation = NULL; _pending_transfer_to_interpreter = false; + _adjusting_comp_level = false; _jvmci._alternate_call_target = NULL; assert(_jvmci._implicit_exception_pc == NULL, "must be"); if (JVMCICounterSize > 0) { diff -r b11f345e4af4 -r 24505bf61633 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon May 09 11:31:54 2016 +0200 +++ b/src/share/vm/runtime/thread.hpp Mon May 09 16:08:16 2016 +0200 @@ -919,10 +919,6 @@ // Communicates the DeoptReason and DeoptAction of the uncommon trap int _pending_deoptimization; - // An object that JVMCI compiled code can use to further describe and - // uniquely identify the speculative optimization guarded by the uncommon trap - oop _pending_failed_speculation; - // Specifies whether the uncommon trap is to bci 0 of a synchronized method // before the monitor has been acquired. bool _pending_monitorenter; @@ -930,6 +926,13 @@ // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter bool _pending_transfer_to_interpreter; + // Guard for re-entrant call to JVMCIRuntime::adjust_comp_level + bool _adjusting_comp_level; + + // An object that JVMCI compiled code can use to further describe and + // uniquely identify the speculative optimization guarded by the uncommon trap + oop _pending_failed_speculation; + // These fields are mutually exclusive in terms of live ranges. union { // Communicates the pc at which the most recent implicit exception occurred @@ -1325,6 +1328,8 @@ #if INCLUDE_JVMCI int pending_deoptimization() const { return _pending_deoptimization; } oop pending_failed_speculation() const { return _pending_failed_speculation; } + bool adjusting_comp_level() const { return _adjusting_comp_level; } + void set_adjusting_comp_level(bool b) { _adjusting_comp_level = b; } bool has_pending_monitorenter() const { return _pending_monitorenter; } void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } void set_pending_deoptimization(int reason) { _pending_deoptimization = reason; }