void CompiledCode::Info::mark(Object* obj, ObjectMark& mark) { auto_mark(obj, mark); mark_inliners(obj, mark); CompiledCode* code = as<CompiledCode>(obj); if(!code->machine_code_) return; MachineCode* mcode = code->machine_code_; mcode->set_mark(); #ifdef ENABLE_LLVM if(code->jit_data()) { code->jit_data()->set_mark(); code->jit_data()->mark_all(code, mark); } for(int i = 0; i < MachineCode::cMaxSpecializations; i++) { if(mcode->specializations[i].jit_data) { mcode->specializations[i].jit_data->set_mark(); mcode->specializations[i].jit_data->mark_all(code, mark); } } #endif for(size_t i = 0; i < mcode->call_site_count(); i++) { size_t index = mcode->call_site_offsets()[i]; Object* old_cache = reinterpret_cast<Object*>(mcode->opcodes[index + 1]); Object* new_cache = mark.call(old_cache); if(new_cache != old_cache) { mcode->opcodes[index + 1] = reinterpret_cast<intptr_t>(new_cache); mark.just_set(code, new_cache); } } for(size_t i = 0; i < mcode->constant_cache_count(); i++) { size_t index = mcode->constant_cache_offsets()[i]; Object* old_cache = reinterpret_cast<Object*>(mcode->opcodes[index + 1]); Object* new_cache = mark.call(old_cache); if(new_cache != old_cache) { mcode->opcodes[index + 1] = reinterpret_cast<intptr_t>(new_cache); mark.just_set(code, new_cache); } } }
CallFrame* LLVMState::find_candidate(STATE, CompiledCode* start, CallFrame* call_frame) { if(!config_.jit_inline_generic) { return call_frame; } int depth = config().jit_limit_search; if(!start) { throw CompileError("find_candidate: null start"); } if(!call_frame) { throw CompileError("find_candidate: null call frame"); } // if(!start) { // start = call_frame->compiled_code; // call_frame = call_frame->previous; // depth--; // } if(debug_search) { std::cout << "> call_count: " << call_frame->compiled_code->machine_code()->call_count << " size: " << call_frame->compiled_code->machine_code()->total << " sends: " << call_frame->compiled_code->machine_code()->call_site_count() << std::endl; call_frame->print_backtrace(state, 1); } if(start->machine_code()->total > (size_t)config_.jit_limit_inline_method) { if(debug_search) { std::cout << "JIT: STOP. reason: trigger method isn't small: " << start->machine_code()->total << " > " << config_.jit_limit_inline_method << std::endl; } return call_frame; } MachineCode* mcode = start->machine_code(); if(mcode->required_args != mcode->total_args) { if(debug_search) { std::cout << "JIT: STOP. reason: trigger method req_args != total_args" << std::endl; } return call_frame; } if(mcode->no_inline_p()) { if(debug_search) { std::cout << "JIT: STOP. reason: trigger method no_inline_p() = true" << std::endl; } return call_frame; } CallFrame* callee = call_frame; call_frame = call_frame->previous; if(!call_frame) return callee; // Now start looking at callers. while(depth-- > 0) { CompiledCode* cur = call_frame->compiled_code; if(!cur) { if(debug_search) { std::cout << "JIT: STOP. reason: synthetic CallFrame hit" << std::endl; } return callee; } MachineCode* mcode = cur->machine_code(); if(debug_search) { std::cout << "> call_count: " << mcode->call_count << " size: " << mcode->total << " sends: " << mcode->call_site_count() << std::endl; call_frame->print_backtrace(state, 1); } /* if(call_frame->block_p() || mcode->required_args != mcode->total_args // has a splat || mcode->call_count < 200 // not called much || mcode->jitted() // already jitted || mcode->parent() // is a block ) return callee; */ if(mcode->required_args != mcode->total_args) { if(debug_search) { std::cout << "JIT: STOP. reason: req_args != total_args" << std::endl; } return callee; } if(mcode->call_count < config_.jit_threshold_inline) { if(debug_search) { std::cout << "JIT: STOP. reason: call_count too small: " << mcode->call_count << " < " << config_.jit_threshold_inline << std::endl; } return callee; } if(mcode->jitted_p()) { if(debug_search) { std::cout << "JIT: STOP. reason: already jitted" << std::endl; } return callee; } if(mcode->no_inline_p()) { if(debug_search) { std::cout << "JIT: STOP. reason: no_inline_p() = true" << std::endl; } return callee; } if(call_frame->jitted_p() || call_frame->inline_method_p()) { return callee; } if(mcode->call_site_count() > eMaxInlineSendCount) { if(debug_search) { std::cout << "JIT: STOP. reason: high send count" << std::endl; } return call_frame; } // if(mcode->required_args != mcode->total_args // has a splat // || mcode->call_count < 200 // not called much // || mcode->jitted() // already jitted // || !mcode->no_inline_p() // method marked as not inlineable // ) return callee; CallFrame* prev = call_frame->previous; if(!prev) { if(debug_search) { std::cout << "JIT: STOP. reason: toplevel method" << std::endl; } return call_frame; } // if(cur->machine_code()->total > SMALL_METHOD_SIZE) { // if(debug_search) { // std::cout << "JIT: STOP. reason: big method: " // << cur->machine_code()->total << " > " // << SMALL_METHOD_SIZE // << "\n"; // } // return call_frame; // } // if(!next || cur->machine_code()->total > SMALL_METHOD_SIZE) return call_frame; callee = call_frame; call_frame = prev; } return callee; }