8150646: Add support for blocking compiles though whitebox API

Co-authored-by: Nils Eliasson <nils.eliasson@oracle.com>
Reviewed-by: kvn, ppunegov, simonis, neliasso
This commit is contained in:
Volker Simonis 2016-03-03 16:21:16 +01:00
parent 59193ab336
commit 173a62a8d6
10 changed files with 238 additions and 70 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -838,12 +838,8 @@ void CompileBroker::compile_method_base(const methodHandle& method,
const methodHandle& hot_method, const methodHandle& hot_method,
int hot_count, int hot_count,
const char* comment, const char* comment,
bool blocking,
Thread* thread) { Thread* thread) {
// do nothing if compiler thread(s) is not available
if (!_initialized) {
return;
}
guarantee(!method->is_abstract(), "cannot compile abstract methods"); guarantee(!method->is_abstract(), "cannot compile abstract methods");
assert(method->method_holder()->is_instance_klass(), assert(method->method_holder()->is_instance_klass(),
"sanity check"); "sanity check");
@ -916,7 +912,6 @@ void CompileBroker::compile_method_base(const methodHandle& method,
// Outputs from the following MutexLocker block: // Outputs from the following MutexLocker block:
CompileTask* task = NULL; CompileTask* task = NULL;
bool blocking = false;
CompileQueue* queue = compile_queue(comp_level); CompileQueue* queue = compile_queue(comp_level);
// Acquire our lock. // Acquire our lock.
@ -946,9 +941,6 @@ void CompileBroker::compile_method_base(const methodHandle& method,
return; return;
} }
// Should this thread wait for completion of the compile?
blocking = is_compile_blocking();
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
if (UseJVMCICompiler) { if (UseJVMCICompiler) {
if (blocking) { if (blocking) {
@ -1034,11 +1026,28 @@ void CompileBroker::compile_method_base(const methodHandle& method,
} }
} }
nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
int comp_level, int comp_level,
const methodHandle& hot_method, int hot_count, const methodHandle& hot_method, int hot_count,
const char* comment, Thread* THREAD) { const char* comment, Thread* THREAD) {
// do nothing if compilebroker is not available
if (!_initialized) {
return NULL;
}
AbstractCompiler *comp = CompileBroker::compiler(comp_level);
assert(comp != NULL, "Ensure we don't compile before compilebroker init");
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD);
DirectivesStack::release(directive);
return nm;
}
nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
int comp_level,
const methodHandle& hot_method, int hot_count,
const char* comment, DirectiveSet* directive,
Thread* THREAD) {
// make sure arguments make sense // make sure arguments make sense
assert(method->method_holder()->is_instance_klass(), "not an instance method"); assert(method->method_holder()->is_instance_klass(), "not an instance method");
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
@ -1051,8 +1060,8 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
// lock, make sure that the compilation // lock, make sure that the compilation
// isn't prohibited in a straightforward way. // isn't prohibited in a straightforward way.
AbstractCompiler *comp = CompileBroker::compiler(comp_level); AbstractCompiler *comp = CompileBroker::compiler(comp_level);
if (comp == NULL || !comp->can_compile_method(method) || if (!comp->can_compile_method(method) ||
compilation_is_prohibited(method, osr_bci, comp_level)) { compilation_is_prohibited(method, osr_bci, comp_level, directive->ExcludeOption)) {
return NULL; return NULL;
} }
@ -1160,7 +1169,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci,
CompilationPolicy::policy()->delay_compilation(method()); CompilationPolicy::policy()->delay_compilation(method());
return NULL; return NULL;
} }
compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD); compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, !directive->BackgroundCompilationOption, THREAD);
} }
// return requested nmethod // return requested nmethod
@ -1217,7 +1226,7 @@ bool CompileBroker::compilation_is_in_queue(const methodHandle& method) {
// CompileBroker::compilation_is_prohibited // CompileBroker::compilation_is_prohibited
// //
// See if this compilation is not allowed. // See if this compilation is not allowed.
bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) { bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded) {
bool is_native = method->is_native(); bool is_native = method->is_native();
// Some compilers may not support the compilation of natives. // Some compilers may not support the compilation of natives.
AbstractCompiler *comp = compiler(comp_level); AbstractCompiler *comp = compiler(comp_level);
@ -1235,11 +1244,6 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os
return true; return true;
} }
// Breaking the abstraction - directives are only used inside a compilation otherwise.
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
bool excluded = directive->ExcludeOption;
DirectivesStack::release(directive);
// The method may be explicitly excluded by the user. // The method may be explicitly excluded by the user.
double scale; double scale;
if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
@ -1304,16 +1308,6 @@ uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandl
return assign_compile_id(method, osr_bci); return assign_compile_id(method, osr_bci);
} }
/**
* Should the current thread block until this compilation request
* has been fulfilled?
*/
bool CompileBroker::is_compile_blocking() {
assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock");
return !BackgroundCompilation;
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// CompileBroker::preload_classes // CompileBroker::preload_classes
void CompileBroker::preload_classes(const methodHandle& method, TRAPS) { void CompileBroker::preload_classes(const methodHandle& method, TRAPS) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -222,8 +222,7 @@ class CompileBroker: AllStatic {
static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS); static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count); static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level); static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded);
static bool is_compile_blocking();
static void preload_classes (const methodHandle& method, TRAPS); static void preload_classes (const methodHandle& method, TRAPS);
static CompileTask* create_compile_task(CompileQueue* queue, static CompileTask* create_compile_task(CompileQueue* queue,
@ -253,6 +252,7 @@ class CompileBroker: AllStatic {
const methodHandle& hot_method, const methodHandle& hot_method,
int hot_count, int hot_count,
const char* comment, const char* comment,
bool blocking,
Thread* thread); Thread* thread);
static CompileQueue* compile_queue(int comp_level); static CompileQueue* compile_queue(int comp_level);
@ -291,6 +291,15 @@ public:
int hot_count, int hot_count,
const char* comment, Thread* thread); const char* comment, Thread* thread);
static nmethod* compile_method(const methodHandle& method,
int osr_bci,
int comp_level,
const methodHandle& hot_method,
int hot_count,
const char* comment,
DirectiveSet* directive,
Thread* thread);
// Acquire any needed locks and assign a compile id // Acquire any needed locks and assign a compile id
static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -472,9 +472,12 @@ void DirectivesStack::push(CompilerDirectives* directive) {
_depth++; _depth++;
} }
void DirectivesStack::pop() { void DirectivesStack::pop(int count) {
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
assert(count > -1, "No negative values");
for (int i = 0; i < count; i++) {
pop_inner(); pop_inner();
}
} }
void DirectivesStack::pop_inner() { void DirectivesStack::pop_inner() {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,7 @@
cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
cflags(PrintInlining, bool, PrintInlining, PrintInlining) \ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \ cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
cflags(BackgroundCompilation, bool, BackgroundCompilation, BackgroundCompilation) \
cflags(ReplayInline, bool, false, ReplayInline) \ cflags(ReplayInline, bool, false, ReplayInline) \
cflags(DumpReplay, bool, false, DumpReplay) \ cflags(DumpReplay, bool, false, DumpReplay) \
cflags(DumpInline, bool, false, DumpInline) \ cflags(DumpInline, bool, false, DumpInline) \
@ -87,7 +88,7 @@ public:
static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp); static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
static DirectiveSet* getDefaultDirective(AbstractCompiler* comp); static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
static void push(CompilerDirectives* directive); static void push(CompilerDirectives* directive);
static void pop(); static void pop(int count);
static bool check_capacity(int request_size, outputStream* st); static bool check_capacity(int request_size, outputStream* st);
static void clear(); static void clear();
static void print(outputStream* st); static void print(outputStream* st);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -55,7 +55,7 @@ void DirectivesParser::clean_tmp() {
assert(_tmp_depth == 0, "Consistency"); assert(_tmp_depth == 0, "Consistency");
} }
bool DirectivesParser::parse_string(const char* text, outputStream* st) { int DirectivesParser::parse_string(const char* text, outputStream* st) {
DirectivesParser cd(text, st); DirectivesParser cd(text, st);
if (cd.valid()) { if (cd.valid()) {
return cd.install_directives(); return cd.install_directives();
@ -63,7 +63,7 @@ bool DirectivesParser::parse_string(const char* text, outputStream* st) {
cd.clean_tmp(); cd.clean_tmp();
st->flush(); st->flush();
st->print_cr("Parsing of compiler directives failed"); st->print_cr("Parsing of compiler directives failed");
return false; return -1;
} }
} }
@ -97,17 +97,17 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream*
buffer[num_read] = '\0'; buffer[num_read] = '\0';
// close file // close file
os::close(file_handle); os::close(file_handle);
return parse_string(buffer, stream); return parse_string(buffer, stream) != -1;
} }
} }
return false; return false;
} }
bool DirectivesParser::install_directives() { int DirectivesParser::install_directives() {
// Check limit // Check limit
if (!DirectivesStack::check_capacity(_tmp_depth, _st)) { if (!DirectivesStack::check_capacity(_tmp_depth, _st)) {
clean_tmp(); clean_tmp();
return false; return 0;
} }
// Pop from internal temporary stack and push to compileBroker. // Pop from internal temporary stack and push to compileBroker.
@ -120,14 +120,14 @@ bool DirectivesParser::install_directives() {
} }
if (i == 0) { if (i == 0) {
_st->print_cr("No directives in file"); _st->print_cr("No directives in file");
return false; return 0;
} else { } else {
_st->print_cr("%i compiler directives added", i); _st->print_cr("%i compiler directives added", i);
if (CompilerDirectivesPrint) { if (CompilerDirectivesPrint) {
// Print entire directives stack after new has been pushed. // Print entire directives stack after new has been pushed.
DirectivesStack::print(_st); DirectivesStack::print(_st);
} }
return true; return i;
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -51,8 +51,8 @@ public:
static bool has_file(); static bool has_file();
static bool parse_from_flag(); static bool parse_from_flag();
static bool parse_from_file(const char* filename, outputStream* st); static bool parse_from_file(const char* filename, outputStream* st);
static bool parse_string(const char* string, outputStream* st); static int parse_string(const char* string, outputStream* st);
bool install_directives(); int install_directives();
private: private:
DirectivesParser(const char* text, outputStream* st); DirectivesParser(const char* text, outputStream* st);

View file

@ -30,6 +30,7 @@
#include "classfile/stringTable.hpp" #include "classfile/stringTable.hpp"
#include "code/codeCache.hpp" #include "code/codeCache.hpp"
#include "compiler/methodMatcher.hpp" #include "compiler/methodMatcher.hpp"
#include "compiler/directivesParser.hpp"
#include "jvmtifiles/jvmtiEnv.hpp" #include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/metadataFactory.hpp" #include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp" #include "memory/metaspaceShared.hpp"
@ -636,6 +637,10 @@ WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject m
WB_END WB_END
WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
// Screen for unavailable/bad comp level
if (CompileBroker::compiler(comp_level) == NULL) {
return false;
}
jmethodID jmid = reflected_method_to_jmid(thread, env, method); jmethodID jmid = reflected_method_to_jmid(thread, env, method);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE); CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
@ -1502,6 +1507,27 @@ void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
} }
} }
WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect))
// can't be in VM when we call JNI
ThreadToNativeFromVM ttnfv(thread);
const char* dir = env->GetStringUTFChars(compDirect, NULL);
int ret;
{
ThreadInVMfromNative ttvfn(thread); // back to VM
ret = DirectivesParser::parse_string(dir, tty);
}
env->ReleaseStringUTFChars(compDirect, dir);
// -1 for error parsing directive. Return 0 as number of directives added.
if (ret == -1) {
ret = 0;
}
return (jint) ret;
WB_END
WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count))
DirectivesStack::pop(count);
WB_END
#define CC (char*) #define CC (char*)
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {
@ -1677,6 +1703,9 @@ static JNINativeMethod methods[] = {
{CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared }, {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
{CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored },
{CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches }, {CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches },
{CC"addCompilerDirective", CC"(Ljava/lang/String;)I",
(void*)&WB_AddCompilerDirective },
{CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective },
}; };
#undef CC #undef CC

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -177,9 +177,7 @@ bool AdvancedThresholdPolicy::is_method_profiled(Method* method) {
// Called with the queue locked and with at least one element // Called with the queue locked and with at least one element
CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
#if INCLUDE_JVMCI
CompileTask *max_blocking_task = NULL; CompileTask *max_blocking_task = NULL;
#endif
CompileTask *max_task = NULL; CompileTask *max_task = NULL;
Method* max_method = NULL; Method* max_method = NULL;
jlong t = os::javaTimeMillis(); jlong t = os::javaTimeMillis();
@ -193,7 +191,8 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
max_method = method; max_method = method;
} else { } else {
// If a method has been stale for some time, remove it from the queue. // If a method has been stale for some time, remove it from the queue.
if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { // Blocking tasks don't become stale
if (!task->is_blocking() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) {
if (PrintTieredEvents) { if (PrintTieredEvents) {
print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level());
} }
@ -210,18 +209,16 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
max_method = method; max_method = method;
} }
} }
#if INCLUDE_JVMCI
if (UseJVMCICompiler && task->is_blocking()) { if (task->is_blocking()) {
if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) { if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) {
max_blocking_task = task; max_blocking_task = task;
} }
} }
#endif
task = next_task; task = next_task;
} }
#if INCLUDE_JVMCI
if (UseJVMCICompiler) {
if (max_blocking_task != NULL) { if (max_blocking_task != NULL) {
// In blocking compilation mode, the CompileBroker will make // In blocking compilation mode, the CompileBroker will make
// compilations submitted by a JVMCI compiler thread non-blocking. These // compilations submitted by a JVMCI compiler thread non-blocking. These
@ -231,8 +228,6 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
max_task = max_blocking_task; max_task = max_blocking_task;
max_method = max_task->method(); max_method = max_task->method();
} }
}
#endif
if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile
&& is_method_profiled(max_method)) { && is_method_profiled(max_method)) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -931,7 +931,7 @@ int CompilerDirectivesAddDCmd::num_arguments() {
} }
void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) { void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) {
DirectivesStack::pop(); DirectivesStack::pop(1);
} }
void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) { void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) {

View file

@ -0,0 +1,137 @@
/*
* Copyright (c) 2016 SAP SE. 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 8150646
* @summary Add support for blocking compiles through whitebox API
* @library /testlibrary /test/lib /
* @build sun.hotspot.WhiteBox
* compiler.testlibrary.CompilerUtils
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
*
* @run main/othervm
* -Xbootclasspath/a:.
* -Xmixed
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -XX:+PrintCompilation
* -XX:CompileCommand=option,BlockingCompilation::foo,PrintInlining
* BlockingCompilation
*/
import java.lang.reflect.Method;
import java.util.Random;
import sun.hotspot.WhiteBox;
import compiler.testlibrary.CompilerUtils;
public class BlockingCompilation {
private static final WhiteBox WB = WhiteBox.getWhiteBox();
private static final Random RANDOM = new Random();
public static int foo() {
return RANDOM.nextInt();
}
public static void main(String[] args) throws Exception {
long sum = 0;
int level = 0;
boolean enqued = false;
Method m = BlockingCompilation.class.getMethod("foo");
int[] levels = CompilerUtils.getAvailableCompilationLevels();
// If there are no compilers available these tests don't make any sense.
if (levels.length == 0) return;
int max_level = levels[levels.length - 1];
// Normal, non-blocking compilation
for (int i = 0; i < 500_000; i++) {
sum += foo();
if (!enqued && WB.isMethodQueuedForCompilation(m)) {
System.out.println("==> " + m + " enqued for compilation in iteration " + i);
enqued = true;
}
if (WB.isMethodCompiled(m)) {
if (WB.getMethodCompilationLevel(m) != level) {
level = WB.getMethodCompilationLevel(m);
System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i);
enqued = false;
if (level == max_level) break;
}
}
}
// This is necessarry because WB.deoptimizeMethod doesn't clear the methods
// MDO and therefore level 3 compilations will be downgraded to level 2.
WB.clearMethodState(m);
// Blocking compilations on all levels, using the default versions of
// WB.enqueueMethodForCompilation() and manually setting compiler directives.
String directive = "[{ match: \"BlockingCompilation.foo\", BackgroundCompilation: false }]";
WB.addCompilerDirective(directive);
for (int l : levels) {
WB.deoptimizeMethod(m);
WB.enqueueMethodForCompilation(m, l);
if (!WB.isMethodCompiled(m) || WB.getMethodCompilationLevel(m) != l) {
String msg = m + " should be compiled at level " + l +
"(but is actually compiled at level " +
WB.getMethodCompilationLevel(m) + ")";
System.out.println("==> " + msg);
throw new Exception(msg);
}
}
WB.removeCompilerDirective(1);
WB.deoptimizeMethod(m);
WB.clearMethodState(m);
level = 0;
enqued = false;
int iteration = 0;
// Normal, non-blocking compilation
for (int i = 0; i < 500_000; i++) {
sum += foo();
if (!enqued && WB.isMethodQueuedForCompilation(m)) {
System.out.println("==> " + m + " enqued for compilation in iteration " + i);
iteration = i;
enqued = true;
}
if (WB.isMethodCompiled(m)) {
if (WB.getMethodCompilationLevel(m) != level) {
level = WB.getMethodCompilationLevel(m);
System.out.println("==> " + m + " compiled at level " + level + " in iteration " + i);
if (level == 4 && iteration == i) {
throw new Exception("This seems to be a blocking compilation although it shouldn't.");
}
enqued = false;
if (level == max_level) break;
}
}
}
}
}