duke@435: /* coleenp@4037: * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #include "precompiled.hpp" stefank@2314: #include "code/compiledIC.hpp" stefank@2314: #include "code/nmethod.hpp" stefank@2314: #include "code/scopeDesc.hpp" stefank@2314: #include "compiler/compilerOracle.hpp" stefank@2314: #include "interpreter/interpreter.hpp" coleenp@4037: #include "oops/methodData.hpp" coleenp@4037: #include "oops/method.hpp" stefank@2314: #include "oops/oop.inline.hpp" stefank@2314: #include "prims/nativeLookup.hpp" iveresov@2630: #include "runtime/advancedThresholdPolicy.hpp" stefank@2314: #include "runtime/compilationPolicy.hpp" stefank@2314: #include "runtime/frame.hpp" stefank@2314: #include "runtime/handles.inline.hpp" stefank@2314: #include "runtime/rframe.hpp" stefank@2314: #include "runtime/simpleThresholdPolicy.hpp" stefank@2314: #include "runtime/stubRoutines.hpp" stefank@2314: #include "runtime/thread.hpp" stefank@2314: #include "runtime/timer.hpp" stefank@2314: #include "runtime/vframe.hpp" stefank@2314: #include "runtime/vm_operations.hpp" stefank@2314: #include "utilities/events.hpp" stefank@2314: #include "utilities/globalDefinitions.hpp" duke@435: duke@435: CompilationPolicy* CompilationPolicy::_policy; duke@435: elapsedTimer CompilationPolicy::_accumulated_time; duke@435: bool CompilationPolicy::_in_vm_startup; duke@435: duke@435: // Determine compilation policy based on command line argument duke@435: void compilationPolicy_init() { duke@435: CompilationPolicy::set_in_vm_startup(DelayCompilationDuringStartup); duke@435: duke@435: switch(CompilationPolicyChoice) { duke@435: case 0: duke@435: CompilationPolicy::set_policy(new SimpleCompPolicy()); duke@435: break; duke@435: duke@435: case 1: duke@435: #ifdef COMPILER2 duke@435: CompilationPolicy::set_policy(new StackWalkCompPolicy()); duke@435: #else duke@435: Unimplemented(); duke@435: #endif duke@435: break; iveresov@2138: case 2: iveresov@2138: #ifdef TIERED iveresov@2138: CompilationPolicy::set_policy(new SimpleThresholdPolicy()); iveresov@2138: #else iveresov@2138: Unimplemented(); iveresov@2138: #endif iveresov@2138: break; iveresov@2630: case 3: iveresov@2630: #ifdef TIERED iveresov@2630: CompilationPolicy::set_policy(new AdvancedThresholdPolicy()); iveresov@2630: #else iveresov@2630: Unimplemented(); iveresov@2630: #endif iveresov@2630: break; duke@435: default: iveresov@2630: fatal("CompilationPolicyChoice must be in the range: [0-3]"); duke@435: } iveresov@2138: CompilationPolicy::policy()->initialize(); duke@435: } duke@435: duke@435: void CompilationPolicy::completed_vm_startup() { duke@435: if (TraceCompilationPolicy) { duke@435: tty->print("CompilationPolicy: completed vm startup.\n"); duke@435: } duke@435: _in_vm_startup = false; duke@435: } duke@435: duke@435: // Returns true if m must be compiled before executing it duke@435: // This is intended to force compiles for methods (usually for duke@435: // debugging) that would otherwise be interpreted for some reason. iveresov@2138: bool CompilationPolicy::must_be_compiled(methodHandle m, int comp_level) { duke@435: if (m->has_compiled_code()) return false; // already compiled iveresov@2138: if (!can_be_compiled(m, comp_level)) return false; duke@435: duke@435: return !UseInterpreter || // must compile all methods kvn@1637: (UseCompiler && AlwaysCompileLoopMethods && m->has_loops() && CompileBroker::should_compile_new_jobs()); // eagerly compile loop methods duke@435: } duke@435: duke@435: // Returns true if m is allowed to be compiled iveresov@2138: bool CompilationPolicy::can_be_compiled(methodHandle m, int comp_level) { duke@435: if (m->is_abstract()) return false; duke@435: if (DontCompileHugeMethods && m->code_size() > HugeMethodLimit) return false; duke@435: never@1609: // Math intrinsics should never be compiled as this can lead to never@1609: // monotonicity problems because the interpreter will prefer the never@1609: // compiled code to the intrinsic version. This can't happen in never@1609: // production because the invocation counter can't be incremented never@1609: // but we shouldn't expose the system to this problem in testing never@1609: // modes. never@1609: if (!AbstractInterpreter::can_be_compiled(m)) { never@1609: return false; never@1609: } iveresov@2138: if (comp_level == CompLevel_all) { iveresov@2138: return !m->is_not_compilable(CompLevel_simple) && !m->is_not_compilable(CompLevel_full_optimization); iveresov@2138: } else { iveresov@2138: return !m->is_not_compilable(comp_level); iveresov@2138: } iveresov@2138: } never@1609: iveresov@2138: bool CompilationPolicy::is_compilation_enabled() { iveresov@2138: // NOTE: CompileBroker::should_compile_new_jobs() checks for UseCompiler iveresov@2138: return !delay_compilation_during_startup() && CompileBroker::should_compile_new_jobs(); duke@435: } duke@435: duke@435: #ifndef PRODUCT duke@435: void CompilationPolicy::print_time() { duke@435: tty->print_cr ("Accumulated compilationPolicy times:"); duke@435: tty->print_cr ("---------------------------"); duke@435: tty->print_cr (" Total: %3.3f sec.", _accumulated_time.seconds()); duke@435: } duke@435: iveresov@2138: void NonTieredCompPolicy::trace_osr_completion(nmethod* osr_nm) { duke@435: if (TraceOnStackReplacement) { duke@435: if (osr_nm == NULL) tty->print_cr("compilation failed"); duke@435: else tty->print_cr("nmethod " INTPTR_FORMAT, osr_nm); duke@435: } duke@435: } duke@435: #endif // !PRODUCT duke@435: iveresov@2138: void NonTieredCompPolicy::initialize() { iveresov@2138: // Setup the compiler thread numbers iveresov@2138: if (CICompilerCountPerCPU) { iveresov@2138: // Example: if CICompilerCountPerCPU is true, then we get iveresov@2138: // max(log2(8)-1,1) = 2 compiler threads on an 8-way machine. iveresov@2138: // May help big-app startup time. iveresov@2138: _compiler_count = MAX2(log2_intptr(os::active_processor_count())-1,1); iveresov@2138: } else { iveresov@2138: _compiler_count = CICompilerCount; iveresov@2138: } iveresov@2138: } iveresov@2138: iveresov@2176: // Note: this policy is used ONLY if TieredCompilation is off. iveresov@2176: // compiler_count() behaves the following way: iveresov@2176: // - with TIERED build (with both COMPILER1 and COMPILER2 defined) it should return iveresov@2176: // zero for the c1 compilation levels, hence the particular ordering of the iveresov@2176: // statements. iveresov@2176: // - the same should happen when COMPILER2 is defined and COMPILER1 is not iveresov@2176: // (server build without TIERED defined). iveresov@2176: // - if only COMPILER1 is defined (client build), zero should be returned for iveresov@2176: // the c2 level. iveresov@2176: // - if neither is defined - always return zero. iveresov@2138: int NonTieredCompPolicy::compiler_count(CompLevel comp_level) { iveresov@2176: assert(!TieredCompilation, "This policy should not be used with TieredCompilation"); iveresov@2176: #ifdef COMPILER2 iveresov@2176: if (is_c2_compile(comp_level)) { iveresov@2176: return _compiler_count; iveresov@2176: } else { iveresov@2176: return 0; iveresov@2176: } iveresov@2176: #endif iveresov@2176: iveresov@2138: #ifdef COMPILER1 iveresov@2138: if (is_c1_compile(comp_level)) { iveresov@2138: return _compiler_count; iveresov@2176: } else { iveresov@2176: return 0; iveresov@2138: } iveresov@2138: #endif iveresov@2138: iveresov@2138: return 0; iveresov@2138: } iveresov@2138: iveresov@2138: void NonTieredCompPolicy::reset_counter_for_invocation_event(methodHandle m) { duke@435: // Make sure invocation and backedge counter doesn't overflow again right away duke@435: // as would be the case for native methods. duke@435: duke@435: // BUT also make sure the method doesn't look like it was never executed. duke@435: // Set carry bit and reduce counter's value to min(count, CompileThreshold/2). duke@435: m->invocation_counter()->set_carry(); duke@435: m->backedge_counter()->set_carry(); duke@435: duke@435: assert(!m->was_never_executed(), "don't reset to 0 -- could be mistaken for never-executed"); duke@435: } duke@435: iveresov@2138: void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) { duke@435: // Delay next back-branch event but pump up invocation counter to triger duke@435: // whole method compilation. duke@435: InvocationCounter* i = m->invocation_counter(); duke@435: InvocationCounter* b = m->backedge_counter(); duke@435: duke@435: // Don't set invocation_counter's value too low otherwise the method will duke@435: // look like immature (ic < ~5300) which prevents the inlining based on duke@435: // the type profiling. duke@435: i->set(i->state(), CompileThreshold); duke@435: // Don't reset counter too low - it is used to check if OSR method is ready. duke@435: b->set(b->state(), CompileThreshold / 2); duke@435: } duke@435: iveresov@2138: // iveresov@2138: // CounterDecay iveresov@2138: // iveresov@2138: // Interates through invocation counters and decrements them. This iveresov@2138: // is done at each safepoint. iveresov@2138: // iveresov@2138: class CounterDecay : public AllStatic { iveresov@2138: static jlong _last_timestamp; coleenp@4037: static void do_method(Method* m) { iveresov@2138: m->invocation_counter()->decay(); iveresov@2138: } iveresov@2138: public: iveresov@2138: static void decay(); iveresov@2138: static bool is_decay_needed() { iveresov@2138: return (os::javaTimeMillis() - _last_timestamp) > CounterDecayMinIntervalLength; iveresov@2138: } iveresov@2138: }; iveresov@2138: iveresov@2138: jlong CounterDecay::_last_timestamp = 0; iveresov@2138: iveresov@2138: void CounterDecay::decay() { iveresov@2138: _last_timestamp = os::javaTimeMillis(); iveresov@2138: iveresov@2138: // This operation is going to be performed only at the end of a safepoint iveresov@2138: // and hence GC's will not be going on, all Java mutators are suspended iveresov@2138: // at this point and hence SystemDictionary_lock is also not needed. iveresov@2138: assert(SafepointSynchronize::is_at_safepoint(), "can only be executed at a safepoint"); iveresov@2138: int nclasses = SystemDictionary::number_of_classes(); iveresov@2138: double classes_per_tick = nclasses * (CounterDecayMinIntervalLength * 1e-3 / iveresov@2138: CounterHalfLifeTime); iveresov@2138: for (int i = 0; i < classes_per_tick; i++) { coleenp@4037: Klass* k = SystemDictionary::try_get_next_class(); coleenp@4037: if (k != NULL && k->oop_is_instance()) { coleenp@4037: InstanceKlass::cast(k)->methods_do(do_method); iveresov@2138: } iveresov@2138: } iveresov@2138: } iveresov@2138: iveresov@2138: // Called at the end of the safepoint iveresov@2138: void NonTieredCompPolicy::do_safepoint_work() { iveresov@2138: if(UseCounterDecay && CounterDecay::is_decay_needed()) { iveresov@2138: CounterDecay::decay(); iveresov@2138: } iveresov@2138: } iveresov@2138: iveresov@2138: void NonTieredCompPolicy::reprofile(ScopeDesc* trap_scope, bool is_osr) { iveresov@2138: ScopeDesc* sd = trap_scope; iveresov@2138: for (; !sd->is_top(); sd = sd->sender()) { iveresov@2138: // Reset ICs of inlined methods, since they can trigger compilations also. iveresov@2138: sd->method()->invocation_counter()->reset(); iveresov@2138: } iveresov@2138: InvocationCounter* c = sd->method()->invocation_counter(); iveresov@2138: if (is_osr) { iveresov@2138: // It was an OSR method, so bump the count higher. iveresov@2138: c->set(c->state(), CompileThreshold); iveresov@2138: } else { iveresov@2138: c->reset(); iveresov@2138: } iveresov@2138: sd->method()->backedge_counter()->reset(); iveresov@2138: } iveresov@2138: iveresov@2138: // This method can be called by any component of the runtime to notify the policy iveresov@2138: // that it's recommended to delay the complation of this method. coleenp@4037: void NonTieredCompPolicy::delay_compilation(Method* method) { iveresov@2138: method->invocation_counter()->decay(); iveresov@2138: method->backedge_counter()->decay(); iveresov@2138: } iveresov@2138: coleenp@4037: void NonTieredCompPolicy::disable_compilation(Method* method) { iveresov@2138: method->invocation_counter()->set_state(InvocationCounter::wait_for_nothing); iveresov@2138: method->backedge_counter()->set_state(InvocationCounter::wait_for_nothing); iveresov@2138: } iveresov@2138: iveresov@2138: CompileTask* NonTieredCompPolicy::select_task(CompileQueue* compile_queue) { iveresov@2138: return compile_queue->first(); iveresov@2138: } iveresov@2138: coleenp@4037: bool NonTieredCompPolicy::is_mature(Method* method) { coleenp@4037: MethodData* mdo = method->method_data(); iveresov@2138: assert(mdo != NULL, "Should be"); iveresov@2138: uint current = mdo->mileage_of(method); iveresov@2138: uint initial = mdo->creation_mileage(); iveresov@2138: if (current < initial) iveresov@2138: return true; // some sort of overflow iveresov@2138: uint target; iveresov@2138: if (ProfileMaturityPercentage <= 0) iveresov@2138: target = (uint) -ProfileMaturityPercentage; // absolute value iveresov@2138: else iveresov@2138: target = (uint)( (ProfileMaturityPercentage * CompileThreshold) / 100 ); iveresov@2138: return (current >= initial + target); iveresov@2138: } iveresov@2138: iveresov@3452: nmethod* NonTieredCompPolicy::event(methodHandle method, methodHandle inlinee, int branch_bci, iveresov@3452: int bci, CompLevel comp_level, nmethod* nm, JavaThread* thread) { iveresov@2138: assert(comp_level == CompLevel_none, "This should be only called from the interpreter"); iveresov@2138: NOT_PRODUCT(trace_frequency_counter_overflow(method, branch_bci, bci)); iveresov@3452: if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) { iveresov@3452: // If certain JVMTI events (e.g. frame pop event) are requested then the iveresov@3452: // thread is forced to remain in interpreted code. This is iveresov@3452: // implemented partly by a check in the run_compiled_code iveresov@3452: // section of the interpreter whether we should skip running iveresov@3452: // compiled code, and partly by skipping OSR compiles for iveresov@3452: // interpreted-only threads. iveresov@3452: if (bci != InvocationEntryBci) { iveresov@3452: reset_counter_for_back_branch_event(method); iveresov@3452: return NULL; iveresov@2138: } iveresov@2138: } iveresov@2138: if (bci == InvocationEntryBci) { iveresov@2138: // when code cache is full, compilation gets switched off, UseCompiler iveresov@2138: // is set to false iveresov@2138: if (!method->has_compiled_code() && UseCompiler) { iveresov@3452: method_invocation_event(method, thread); iveresov@2138: } else { iveresov@2138: // Force counter overflow on method entry, even if no compilation iveresov@2138: // happened. (The method_invocation_event call does this also.) iveresov@2138: reset_counter_for_invocation_event(method); iveresov@2138: } iveresov@2138: // compilation at an invocation overflow no longer goes and retries test for iveresov@2138: // compiled method. We always run the loser of the race as interpreted. iveresov@2138: // so return NULL iveresov@2138: return NULL; iveresov@2138: } else { iveresov@2138: // counter overflow in a loop => try to do on-stack-replacement iveresov@2138: nmethod* osr_nm = method->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true); iveresov@2138: NOT_PRODUCT(trace_osr_request(method, osr_nm, bci)); iveresov@2138: // when code cache is full, we should not compile any more... iveresov@2138: if (osr_nm == NULL && UseCompiler) { iveresov@3452: method_back_branch_event(method, bci, thread); iveresov@2138: osr_nm = method->lookup_osr_nmethod_for(bci, CompLevel_highest_tier, true); iveresov@2138: } iveresov@2138: if (osr_nm == NULL) { iveresov@2138: reset_counter_for_back_branch_event(method); iveresov@2138: return NULL; iveresov@2138: } iveresov@2138: return osr_nm; iveresov@2138: } iveresov@2138: return NULL; iveresov@2138: } iveresov@2138: iveresov@2138: #ifndef PRODUCT iveresov@2138: void NonTieredCompPolicy::trace_frequency_counter_overflow(methodHandle m, int branch_bci, int bci) { iveresov@2138: if (TraceInvocationCounterOverflow) { iveresov@2138: InvocationCounter* ic = m->invocation_counter(); iveresov@2138: InvocationCounter* bc = m->backedge_counter(); iveresov@2138: ResourceMark rm; iveresov@2138: const char* msg = iveresov@2138: bci == InvocationEntryBci iveresov@2138: ? "comp-policy cntr ovfl @ %d in entry of " iveresov@2138: : "comp-policy cntr ovfl @ %d in loop of "; iveresov@2138: tty->print(msg, bci); iveresov@2138: m->print_value(); iveresov@2138: tty->cr(); iveresov@2138: ic->print(); iveresov@2138: bc->print(); iveresov@2138: if (ProfileInterpreter) { iveresov@2138: if (bci != InvocationEntryBci) { coleenp@4037: MethodData* mdo = m->method_data(); iveresov@2138: if (mdo != NULL) { iveresov@2138: int count = mdo->bci_to_data(branch_bci)->as_JumpData()->taken(); iveresov@2138: tty->print_cr("back branch count = %d", count); iveresov@2138: } iveresov@2138: } iveresov@2138: } iveresov@2138: } iveresov@2138: } iveresov@2138: iveresov@2138: void NonTieredCompPolicy::trace_osr_request(methodHandle method, nmethod* osr, int bci) { iveresov@2138: if (TraceOnStackReplacement) { iveresov@2138: ResourceMark rm; iveresov@2138: tty->print(osr != NULL ? "Reused OSR entry for " : "Requesting OSR entry for "); iveresov@2138: method->print_short_name(tty); iveresov@2138: tty->print_cr(" at bci %d", bci); iveresov@2138: } iveresov@2138: } iveresov@2138: #endif // !PRODUCT iveresov@2138: duke@435: // SimpleCompPolicy - compile current method duke@435: iveresov@3452: void SimpleCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { twisti@4111: const int comp_level = CompLevel_highest_tier; twisti@4111: const int hot_count = m->invocation_count(); duke@435: reset_counter_for_invocation_event(m); duke@435: const char* comment = "count"; duke@435: iveresov@2138: if (is_compilation_enabled() && can_be_compiled(m)) { duke@435: nmethod* nm = m->code(); duke@435: if (nm == NULL ) { twisti@4111: CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, comment, thread); duke@435: } duke@435: } duke@435: } duke@435: iveresov@3452: void SimpleCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { twisti@4111: const int comp_level = CompLevel_highest_tier; twisti@4111: const int hot_count = m->backedge_count(); duke@435: const char* comment = "backedge_count"; duke@435: twisti@4111: if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { twisti@4111: CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); twisti@4111: NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) duke@435: } duke@435: } duke@435: // StackWalkCompPolicy - walk up stack to find a suitable method to compile duke@435: duke@435: #ifdef COMPILER2 duke@435: const char* StackWalkCompPolicy::_msg = NULL; duke@435: duke@435: duke@435: // Consider m for compilation iveresov@3452: void StackWalkCompPolicy::method_invocation_event(methodHandle m, JavaThread* thread) { twisti@4111: const int comp_level = CompLevel_highest_tier; twisti@4111: const int hot_count = m->invocation_count(); duke@435: reset_counter_for_invocation_event(m); duke@435: const char* comment = "count"; duke@435: iveresov@2138: if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m)) { iveresov@3452: ResourceMark rm(thread); duke@435: frame fr = thread->last_frame(); duke@435: assert(fr.is_interpreted_frame(), "must be interpreted"); duke@435: assert(fr.interpreter_frame_method() == m(), "bad method"); duke@435: duke@435: if (TraceCompilationPolicy) { duke@435: tty->print("method invocation trigger: "); duke@435: m->print_short_name(tty); duke@435: tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", (address)m(), m->code_size()); duke@435: } duke@435: RegisterMap reg_map(thread, false); duke@435: javaVFrame* triggerVF = thread->last_java_vframe(®_map); duke@435: // triggerVF is the frame that triggered its counter duke@435: RFrame* first = new InterpretedRFrame(triggerVF->fr(), thread, m); duke@435: duke@435: if (first->top_method()->code() != NULL) { duke@435: // called obsolete method/nmethod -- no need to recompile duke@435: if (TraceCompilationPolicy) tty->print_cr(" --> " INTPTR_FORMAT, first->top_method()->code()); duke@435: } else { duke@435: if (TimeCompilationPolicy) accumulated_time()->start(); duke@435: GrowableArray* stack = new GrowableArray(50); duke@435: stack->push(first); duke@435: RFrame* top = findTopInlinableFrame(stack); duke@435: if (TimeCompilationPolicy) accumulated_time()->stop(); duke@435: assert(top != NULL, "findTopInlinableFrame returned null"); duke@435: if (TraceCompilationPolicy) top->print(); twisti@4111: CompileBroker::compile_method(top->top_method(), InvocationEntryBci, comp_level, iveresov@3452: m, hot_count, comment, thread); duke@435: } duke@435: } duke@435: } duke@435: iveresov@3452: void StackWalkCompPolicy::method_back_branch_event(methodHandle m, int bci, JavaThread* thread) { twisti@4111: const int comp_level = CompLevel_highest_tier; twisti@4111: const int hot_count = m->backedge_count(); duke@435: const char* comment = "backedge_count"; duke@435: twisti@4111: if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m)) { twisti@4111: CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); twisti@4111: NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) duke@435: } duke@435: } duke@435: duke@435: RFrame* StackWalkCompPolicy::findTopInlinableFrame(GrowableArray* stack) { duke@435: // go up the stack until finding a frame that (probably) won't be inlined duke@435: // into its caller duke@435: RFrame* current = stack->at(0); // current choice for stopping duke@435: assert( current && !current->is_compiled(), "" ); duke@435: const char* msg = NULL; duke@435: duke@435: while (1) { duke@435: duke@435: // before going up the stack further, check if doing so would get us into duke@435: // compiled code duke@435: RFrame* next = senderOf(current, stack); duke@435: if( !next ) // No next frame up the stack? duke@435: break; // Then compile with current frame duke@435: duke@435: methodHandle m = current->top_method(); duke@435: methodHandle next_m = next->top_method(); duke@435: duke@435: if (TraceCompilationPolicy && Verbose) { duke@435: tty->print("[caller: "); duke@435: next_m->print_short_name(tty); duke@435: tty->print("] "); duke@435: } duke@435: duke@435: if( !Inline ) { // Inlining turned off duke@435: msg = "Inlining turned off"; duke@435: break; duke@435: } duke@435: if (next_m->is_not_compilable()) { // Did fail to compile this before/ duke@435: msg = "caller not compilable"; duke@435: break; duke@435: } duke@435: if (next->num() > MaxRecompilationSearchLength) { duke@435: // don't go up too high when searching for recompilees duke@435: msg = "don't go up any further: > MaxRecompilationSearchLength"; duke@435: break; duke@435: } duke@435: if (next->distance() > MaxInterpretedSearchLength) { duke@435: // don't go up too high when searching for recompilees duke@435: msg = "don't go up any further: next > MaxInterpretedSearchLength"; duke@435: break; duke@435: } duke@435: // Compiled frame above already decided not to inline; duke@435: // do not recompile him. duke@435: if (next->is_compiled()) { duke@435: msg = "not going up into optimized code"; duke@435: break; duke@435: } duke@435: duke@435: // Interpreted frame above us was already compiled. Do not force duke@435: // a recompile, although if the frame above us runs long enough an duke@435: // OSR might still happen. duke@435: if( current->is_interpreted() && next_m->has_compiled_code() ) { duke@435: msg = "not going up -- already compiled caller"; duke@435: break; duke@435: } duke@435: duke@435: // Compute how frequent this call site is. We have current method 'm'. duke@435: // We know next method 'next_m' is interpreted. Find the call site and duke@435: // check the various invocation counts. duke@435: int invcnt = 0; // Caller counts duke@435: if (ProfileInterpreter) { duke@435: invcnt = next_m->interpreter_invocation_count(); duke@435: } duke@435: int cnt = 0; // Call site counts duke@435: if (ProfileInterpreter && next_m->method_data() != NULL) { duke@435: ResourceMark rm; duke@435: int bci = next->top_vframe()->bci(); duke@435: ProfileData* data = next_m->method_data()->bci_to_data(bci); duke@435: if (data != NULL && data->is_CounterData()) duke@435: cnt = data->as_CounterData()->count(); duke@435: } duke@435: duke@435: // Caller counts / call-site counts; i.e. is this call site duke@435: // a hot call site for method next_m? duke@435: int freq = (invcnt) ? cnt/invcnt : cnt; duke@435: duke@435: // Check size and frequency limits duke@435: if ((msg = shouldInline(m, freq, cnt)) != NULL) { duke@435: break; duke@435: } duke@435: // Check inlining negative tests duke@435: if ((msg = shouldNotInline(m)) != NULL) { duke@435: break; duke@435: } duke@435: duke@435: duke@435: // If the caller method is too big or something then we do not want to duke@435: // compile it just to inline a method iveresov@2138: if (!can_be_compiled(next_m)) { duke@435: msg = "caller cannot be compiled"; duke@435: break; duke@435: } duke@435: duke@435: if( next_m->name() == vmSymbols::class_initializer_name() ) { duke@435: msg = "do not compile class initializer (OSR ok)"; duke@435: break; duke@435: } duke@435: duke@435: if (TraceCompilationPolicy && Verbose) { duke@435: tty->print("\n\t check caller: "); duke@435: next_m->print_short_name(tty); duke@435: tty->print(" ( interpreted " INTPTR_FORMAT ", size=%d ) ", (address)next_m(), next_m->code_size()); duke@435: } duke@435: duke@435: current = next; duke@435: } duke@435: duke@435: assert( !current || !current->is_compiled(), "" ); duke@435: duke@435: if (TraceCompilationPolicy && msg) tty->print("(%s)\n", msg); duke@435: duke@435: return current; duke@435: } duke@435: duke@435: RFrame* StackWalkCompPolicy::senderOf(RFrame* rf, GrowableArray* stack) { duke@435: RFrame* sender = rf->caller(); duke@435: if (sender && sender->num() == stack->length()) stack->push(sender); duke@435: return sender; duke@435: } duke@435: duke@435: duke@435: const char* StackWalkCompPolicy::shouldInline(methodHandle m, float freq, int cnt) { duke@435: // Allows targeted inlining duke@435: // positive filter: should send be inlined? returns NULL (--> yes) duke@435: // or rejection msg duke@435: int max_size = MaxInlineSize; duke@435: int cost = m->code_size(); duke@435: duke@435: // Check for too many throws (and not too huge) duke@435: if (m->interpreter_throwout_count() > InlineThrowCount && cost < InlineThrowMaxSize ) { duke@435: return NULL; duke@435: } duke@435: duke@435: // bump the max size if the call is frequent duke@435: if ((freq >= InlineFrequencyRatio) || (cnt >= InlineFrequencyCount)) { duke@435: if (TraceFrequencyInlining) { duke@435: tty->print("(Inlined frequent method)\n"); duke@435: m->print(); duke@435: } duke@435: max_size = FreqInlineSize; duke@435: } duke@435: if (cost > max_size) { duke@435: return (_msg = "too big"); duke@435: } duke@435: return NULL; duke@435: } duke@435: duke@435: duke@435: const char* StackWalkCompPolicy::shouldNotInline(methodHandle m) { duke@435: // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg duke@435: if (m->is_abstract()) return (_msg = "abstract method"); duke@435: // note: we allow ik->is_abstract() coleenp@4037: if (!InstanceKlass::cast(m->method_holder())->is_initialized()) return (_msg = "method holder not initialized"); duke@435: if (m->is_native()) return (_msg = "native method"); duke@435: nmethod* m_code = m->code(); twisti@2103: if (m_code != NULL && m_code->code_size() > InlineSmallCode) duke@435: return (_msg = "already compiled into a big method"); duke@435: duke@435: // use frequency-based objections only for non-trivial methods duke@435: if (m->code_size() <= MaxTrivialSize) return NULL; duke@435: if (UseInterpreter) { // don't use counts with -Xcomp duke@435: if ((m->code() == NULL) && m->was_never_executed()) return (_msg = "never executed"); duke@435: if (!m->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) return (_msg = "executed < MinInliningThreshold times"); duke@435: } coleenp@4037: if (Method::has_unloaded_classes_in_signature(m, JavaThread::current())) return (_msg = "unloaded signature classes"); duke@435: duke@435: return NULL; duke@435: } duke@435: duke@435: duke@435: duke@435: #endif // COMPILER2