--- old/src/share/vm/compiler/compileBroker.cpp 2015-09-22 16:26:51.649641945 +0200 +++ new/src/share/vm/compiler/compileBroker.cpp 2015-09-22 16:26:51.537641949 +0200 @@ -29,6 +29,7 @@ #include "compiler/compileBroker.hpp" #include "compiler/compileLog.hpp" #include "compiler/compilerOracle.hpp" +#include "compiler/directivesparser.hpp" #include "interpreter/linkResolver.hpp" #include "memory/allocation.inline.hpp" #include "oops/methodData.hpp" @@ -100,6 +101,7 @@ // The installed compiler(s) AbstractCompiler* CompileBroker::_compilers[2]; +DirectivesStack* CompileBroker::_dirstack; // These counters are used to assign an unique ID to each compilation. volatile jint CompileBroker::_compilation_id = 0; @@ -197,10 +199,25 @@ static CompilationLog* _compilation_log = NULL; -void compileBroker_init() { +bool compileBroker_init() { if (LogEvents) { _compilation_log = new CompilationLog(); } + + // init directives stack and add default directives + CompileBroker::set_dirstack(new DirectivesStack()); + + /*CompilerDirectives* _default_directives = new CompilerDirectives(); + char str[] = "*.*"; + const char* error_msg = NULL; + _default_directives->add_match(str, error_msg); + assert(error_msg == NULL, "Must succeed."); + CompileBroker::dirstack()->push(_default_directives);*/ + + if (DirectivesParser::has_file()) { + DirectivesParser::parse_from_flag(); + } + return true; } CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { @@ -1143,11 +1160,19 @@ return true; } + // Breaking the abstraction - directives are only used inside a compilation otherwise. + DirectiveSet* dirset = dirstack()->getMatchingDirective(method, comp_level); + bool excluded = !dirset->EnabledOption; + { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + dirset->directive()->dec_refcount(); + } + // The method may be explicitly excluded by the user. bool quietly; double scale; - if (CompilerOracle::should_exclude(method, quietly) - || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { + if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { + bool quietly = CompilerOracle::should_exclude_quietly(); if (!quietly) { // This does not happen quietly... ResourceMark rm; @@ -1299,9 +1324,12 @@ } { + DirectiveSet* dirset = _dirstack->peak(comp); + assert(dirset->directive()->is_default_directive(), "Consistency"); + // Must switch to native to allocate ci_env ThreadToNativeFromVM ttn(thread); - ciEnv ci_env(NULL, system_dictionary_modification_counter); + ciEnv ci_env(NULL, dirset, system_dictionary_modification_counter); // Cache Jvmti state ci_env.cache_jvmti_state(); // Cache DTrace flags @@ -1311,7 +1339,6 @@ ThreadInVMfromNative tv(thread); ResetNoHandleMark rnhm; - if (!comp->is_shark()) { // Perform per-thread and global initializations comp->initialize(); @@ -1558,6 +1585,117 @@ tty->print("%s", s.as_string()); } +void CompileBroker::print_directives(outputStream* st) { + dirstack()->print(st); +} + +DirectivesStack* CompileBroker::dirstack() { + return _dirstack; +} + +void CompileBroker::set_dirstack(DirectivesStack* stack) { + _dirstack = stack; +} + +// Create a new dirstack and push a default directive +DirectivesStack::DirectivesStack() : _depth(0), _top(NULL), _bottom(NULL) +{ + CompilerDirectives* _default_directives = new CompilerDirectives(); + char str[] = "*.*"; + const char* error_msg = NULL; + _default_directives->add_match(str, error_msg); + assert(error_msg == NULL, "Must succeed."); + push(_default_directives); +} + +DirectiveSet* DirectivesStack::peak(AbstractCompiler* comp) { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + + assert(_top != NULL, "Must never be empty"); + if (comp->is_c1()) { + return _top->get_for(CompilerDirectives::TargetC1); + } else { + assert(comp->is_c2(), "Must be c2"); + return _top->get_for(CompilerDirectives::TargetC2); + } + // CMH handle shark and others. +} + +void DirectivesStack::push(CompilerDirectives* directive) { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + + directive->inc_refcount(); + if (_top == NULL) { + assert(_bottom == NULL, "There can only be one default directive"); + _bottom = directive; // default directive, can never be removed. + } + + directive->set_next(_top); + _top = directive; + _depth++; + + if (PrintCompilerDirectives) { + directive->print(tty); + } +} + +void DirectivesStack::pop() { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + pop_inner(); +} + +void DirectivesStack::pop_inner() { + assert(DirectivesStack_lock->owned_by_self(), ""); + + if (_top->next() == NULL) { + return; // Do nothing - dont allow an empty stack + } + CompilerDirectives* tmp = _top; + _top = _top->next(); + _depth--; + tmp->dec_refcount(); + return; +} + +void DirectivesStack::clear() { + // holding the lock during the whole operation ensuring consistent result + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + while (_top->next() != NULL) { + DirectivesStack::pop_inner(); + } +} + +void DirectivesStack::print(outputStream* st) { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + CompilerDirectives* tmp = _top; + while (tmp != NULL) { + tmp->print(st); + tmp = tmp->next(); + } +} + +DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle mh, int comp_level) { + assert(_depth > 0, "Must never be empty"); + CompilerDirectives* dir = _top; + assert(dir != NULL, "Must be initialized"); + + DirectiveSet* match = NULL; + { + MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); + while (dir != NULL) { + if (dir->is_default_directive() || dir->match(mh, comp_level)) { + match = dir->get_for(comp_level); + break; + } + dir = dir->next(); + } + } + guarantee(match != NULL, "There should always be a default directive that matches"); + + // Check for legacy compile commands update, without DirectivesStack_lock + return match->late_cc_init(mh); +} + // ------------------------------------------------------------------ // CompileBroker::invoke_compiler_on_method // @@ -1584,16 +1722,20 @@ bool should_log = (thread->log() != NULL); bool should_break = false; int task_level = task->comp_level(); + + // Look up matching directives + DirectiveSet* dir = CompileBroker::_dirstack->getMatchingDirective(task->method(), task_level); + + should_break = dir->BreakAtExecuteOption || task->check_break_at_flags(); + if (should_log && !dir->LogOption) { + dir->set_Log((void*)false); + } { // create the handle inside it's own block so it can't // accidentally be referenced once the thread transitions to // native. The NoHandleMark before the transition should catch // any cases where this occurs in the future. methodHandle method(thread, task->method()); - should_break = check_break_at(method, compile_id, is_osr); - if (should_log && !CompilerOracle::should_log(method)) { - should_log = false; - } assert(!method->is_native(), "no longer compile natives"); // Save information about this method in case of failure. @@ -1616,10 +1758,7 @@ NoHandleMark nhm; ThreadToNativeFromVM ttn(thread); - ciEnv ci_env(task, system_dictionary_modification_counter); - if (should_break) { - ci_env.set_break_at_compile(true); - } + ciEnv ci_env(task, dir, system_dictionary_modification_counter); if (should_log) { ci_env.set_log(thread->log()); } @@ -1881,21 +2020,6 @@ JNIHandleBlock::release_block(compile_handles, thread); // may block } - -// ------------------------------------------------------------------ -// CompileBroker::check_break_at -// -// Should the compilation break at the current compilation. -bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) { - if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) { - return true; - } else if( CompilerOracle::should_break_at(method) ) { // break when compiling - return true; - } else { - return (compile_id == CIBreakAt); - } -} - // ------------------------------------------------------------------ // CompileBroker::collect_statistics // @@ -2075,3 +2199,4 @@ st->cr(); #endif } +