diff options
Diffstat (limited to 'chromium/v8/src/runtime-profiler.cc')
-rw-r--r-- | chromium/v8/src/runtime-profiler.cc | 290 |
1 files changed, 60 insertions, 230 deletions
diff --git a/chromium/v8/src/runtime-profiler.cc b/chromium/v8/src/runtime-profiler.cc index 691fc666419..dddcad060de 100644 --- a/chromium/v8/src/runtime-profiler.cc +++ b/chromium/v8/src/runtime-profiler.cc @@ -1,67 +1,26 @@ // Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "v8.h" - -#include "runtime-profiler.h" - -#include "assembler.h" -#include "bootstrapper.h" -#include "code-stubs.h" -#include "compilation-cache.h" -#include "execution.h" -#include "full-codegen.h" -#include "global-handles.h" -#include "isolate-inl.h" -#include "mark-compact.h" -#include "platform.h" -#include "scopeinfo.h" +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -namespace v8 { -namespace internal { - - -// Optimization sampler constants. -static const int kSamplerFrameCount = 2; - -// Constants for statistical profiler. -static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; +#include "src/v8.h" -static const int kSamplerTicksBetweenThresholdAdjustment = 32; +#include "src/runtime-profiler.h" -static const int kSamplerThresholdInit = 3; -static const int kSamplerThresholdMin = 1; -static const int kSamplerThresholdDelta = 1; +#include "src/assembler.h" +#include "src/bootstrapper.h" +#include "src/code-stubs.h" +#include "src/compilation-cache.h" +#include "src/execution.h" +#include "src/full-codegen.h" +#include "src/global-handles.h" +#include "src/isolate-inl.h" +#include "src/mark-compact.h" +#include "src/platform.h" +#include "src/scopeinfo.h" -static const int kSamplerThresholdSizeFactorInit = 3; - -static const int kSizeLimit = 1500; +namespace v8 { +namespace internal { -// Constants for counter based profiler. // Number of times a function has to be seen on the stack before it is // optimized. @@ -84,7 +43,7 @@ static const int kOSRCodeSizeAllowanceBase = 100 * FullCodeGenerator::kCodeSizeMultiplier; static const int kOSRCodeSizeAllowancePerTick = - 3 * FullCodeGenerator::kCodeSizeMultiplier; + 4 * FullCodeGenerator::kCodeSizeMultiplier; // Maximum size in bytes of generated code for a function to be optimized // the very first time it is seen on the stack. @@ -94,14 +53,7 @@ static const int kMaxSizeEarlyOpt = RuntimeProfiler::RuntimeProfiler(Isolate* isolate) : isolate_(isolate), - sampler_threshold_(kSamplerThresholdInit), - sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit), - sampler_ticks_until_threshold_adjustment_( - kSamplerTicksBetweenThresholdAdjustment), - sampler_window_position_(0), - any_ic_changed_(false), - code_generated_(false) { - ClearSampleBuffer(); + any_ic_changed_(false) { } @@ -149,11 +101,11 @@ void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) { // recompilation race. This goes away as soon as OSR becomes one-shot. return; } - ASSERT(!function->IsInRecompileQueue()); - function->MarkForConcurrentRecompilation(); + ASSERT(!function->IsInOptimizationQueue()); + function->MarkForConcurrentOptimization(); } else { // The next call to the function will trigger optimization. - function->MarkForLazyRecompilation(); + function->MarkForOptimization(); } } @@ -189,38 +141,6 @@ void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) { } -void RuntimeProfiler::ClearSampleBuffer() { - memset(sampler_window_, 0, sizeof(sampler_window_)); - memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_)); -} - - -int RuntimeProfiler::LookupSample(JSFunction* function) { - int weight = 0; - for (int i = 0; i < kSamplerWindowSize; i++) { - Object* sample = sampler_window_[i]; - if (sample != NULL) { - bool fits = FLAG_lookup_sample_by_shared - ? (function->shared() == JSFunction::cast(sample)->shared()) - : (function == JSFunction::cast(sample)); - if (fits) { - weight += sampler_window_weight_[i]; - } - } - } - return weight; -} - - -void RuntimeProfiler::AddSample(JSFunction* function, int weight) { - ASSERT(IsPowerOf2(kSamplerWindowSize)); - sampler_window_[sampler_window_position_] = function; - sampler_window_weight_[sampler_window_position_] = weight; - sampler_window_position_ = (sampler_window_position_ + 1) & - (kSamplerWindowSize - 1); -} - - void RuntimeProfiler::OptimizeNow() { HandleScope scope(isolate_); @@ -231,39 +151,29 @@ void RuntimeProfiler::OptimizeNow() { // Run through the JavaScript frames and collect them. If we already // have a sample of the function, we mark it for optimizations // (eagerly or lazily). - JSFunction* samples[kSamplerFrameCount]; - int sample_count = 0; int frame_count = 0; - int frame_count_limit = FLAG_watch_ic_patching ? FLAG_frame_count - : kSamplerFrameCount; + int frame_count_limit = FLAG_frame_count; for (JavaScriptFrameIterator it(isolate_); frame_count++ < frame_count_limit && !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); JSFunction* function = frame->function(); - if (!FLAG_watch_ic_patching) { - // Adjust threshold each time we have processed - // a certain number of ticks. - if (sampler_ticks_until_threshold_adjustment_ > 0) { - sampler_ticks_until_threshold_adjustment_--; - if (sampler_ticks_until_threshold_adjustment_ <= 0) { - // If the threshold is not already at the minimum - // modify and reset the ticks until next adjustment. - if (sampler_threshold_ > kSamplerThresholdMin) { - sampler_threshold_ -= kSamplerThresholdDelta; - sampler_ticks_until_threshold_adjustment_ = - kSamplerTicksBetweenThresholdAdjustment; - } - } - } - } - SharedFunctionInfo* shared = function->shared(); Code* shared_code = shared->code(); + List<JSFunction*> functions(4); + frame->GetFunctions(&functions); + for (int i = functions.length(); --i >= 0; ) { + SharedFunctionInfo* shared_function_info = functions[i]->shared(); + int ticks = shared_function_info->profiler_ticks(); + if (ticks < Smi::kMaxValue) { + shared_function_info->set_profiler_ticks(ticks + 1); + } + } + if (shared_code->kind() != Code::FUNCTION) continue; - if (function->IsInRecompileQueue()) continue; + if (function->IsInOptimizationQueue()) continue; if (FLAG_always_osr && shared_code->allow_osr_at_loop_nesting_level() == 0) { @@ -275,8 +185,8 @@ void RuntimeProfiler::OptimizeNow() { } // Fall through and do a normal optimized compile as well. } else if (!frame->is_optimized() && - (function->IsMarkedForLazyRecompilation() || - function->IsMarkedForConcurrentRecompilation() || + (function->IsMarkedForOptimization() || + function->IsMarkedForConcurrentOptimization() || function->IsOptimized())) { // Attempt OSR if we are still running unoptimized code even though the // the function has long been marked or even already been optimized. @@ -322,116 +232,36 @@ void RuntimeProfiler::OptimizeNow() { } if (!function->IsOptimizable()) continue; - if (FLAG_watch_ic_patching) { - int ticks = shared_code->profiler_ticks(); + int ticks = shared_code->profiler_ticks(); - if (ticks >= kProfilerTicksBeforeOptimization) { - int typeinfo, total, percentage; - GetICCounts(shared_code, &typeinfo, &total, &percentage); - if (percentage >= FLAG_type_info_threshold) { - // If this particular function hasn't had any ICs patched for enough - // ticks, optimize it now. - Optimize(function, "hot and stable"); - } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { - Optimize(function, "not much type info but very hot"); - } else { - shared_code->set_profiler_ticks(ticks + 1); - if (FLAG_trace_opt_verbose) { - PrintF("[not yet optimizing "); - function->PrintName(); - PrintF(", not enough type info: %d/%d (%d%%)]\n", - typeinfo, total, percentage); - } - } - } else if (!any_ic_changed_ && - shared_code->instruction_size() < kMaxSizeEarlyOpt) { - // If no IC was patched since the last tick and this function is very - // small, optimistically optimize it now. - Optimize(function, "small function"); + if (ticks >= kProfilerTicksBeforeOptimization) { + int typeinfo, total, percentage; + GetICCounts(shared_code, &typeinfo, &total, &percentage); + if (percentage >= FLAG_type_info_threshold) { + // If this particular function hasn't had any ICs patched for enough + // ticks, optimize it now. + Optimize(function, "hot and stable"); + } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { + Optimize(function, "not much type info but very hot"); } else { shared_code->set_profiler_ticks(ticks + 1); + if (FLAG_trace_opt_verbose) { + PrintF("[not yet optimizing "); + function->PrintName(); + PrintF(", not enough type info: %d/%d (%d%%)]\n", + typeinfo, total, percentage); + } } - } else { // !FLAG_watch_ic_patching - samples[sample_count++] = function; - - int function_size = function->shared()->SourceSize(); - int threshold_size_factor = (function_size > kSizeLimit) - ? sampler_threshold_size_factor_ - : 1; - - int threshold = sampler_threshold_ * threshold_size_factor; - - if (LookupSample(function) >= threshold) { - Optimize(function, "sampler window lookup"); - } - } - } - if (FLAG_watch_ic_patching) { - any_ic_changed_ = false; - } else { // !FLAG_watch_ic_patching - // Add the collected functions as samples. It's important not to do - // this as part of collecting them because this will interfere with - // the sample lookup in case of recursive functions. - for (int i = 0; i < sample_count; i++) { - AddSample(samples[i], kSamplerFrameWeight[i]); - } - } -} - - -void RuntimeProfiler::SetUp() { - if (!FLAG_watch_ic_patching) { - ClearSampleBuffer(); - } -} - - -void RuntimeProfiler::Reset() { - if (!FLAG_watch_ic_patching) { - sampler_threshold_ = kSamplerThresholdInit; - sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit; - sampler_ticks_until_threshold_adjustment_ = - kSamplerTicksBetweenThresholdAdjustment; - } -} - - -void RuntimeProfiler::TearDown() { - // Nothing to do. -} - - -// Update the pointers in the sampler window after a GC. -void RuntimeProfiler::UpdateSamplesAfterScavenge() { - for (int i = 0; i < kSamplerWindowSize; i++) { - Object* function = sampler_window_[i]; - if (function != NULL && isolate_->heap()->InNewSpace(function)) { - MapWord map_word = HeapObject::cast(function)->map_word(); - if (map_word.IsForwardingAddress()) { - sampler_window_[i] = map_word.ToForwardingAddress(); - } else { - sampler_window_[i] = NULL; - } - } - } -} - - -void RuntimeProfiler::RemoveDeadSamples() { - for (int i = 0; i < kSamplerWindowSize; i++) { - Object* function = sampler_window_[i]; - if (function != NULL && - !Marking::MarkBitFrom(HeapObject::cast(function)).Get()) { - sampler_window_[i] = NULL; + } else if (!any_ic_changed_ && + shared_code->instruction_size() < kMaxSizeEarlyOpt) { + // If no IC was patched since the last tick and this function is very + // small, optimistically optimize it now. + Optimize(function, "small function"); + } else { + shared_code->set_profiler_ticks(ticks + 1); } } -} - - -void RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) { - for (int i = 0; i < kSamplerWindowSize; i++) { - visitor->VisitPointer(&sampler_window_[i]); - } + any_ic_changed_ = false; } |