runtime-profiler.cc revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without
3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met:
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions of source code must retain the above copyright
7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions in binary form must reproduce the above
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       copyright notice, this list of conditions and the following
10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       with the distribution.
12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       contributors may be used to endorse or promote products derived
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       from this software without specific prior written permission.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "runtime-profiler.h"
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "assembler.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "code-stubs.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "compilation-cache.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "execution.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "global-handles.h"
38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "mark-compact.h"
3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "platform.h"
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopeinfo.h"
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Optimization sampler constants.
47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerFrameCount = 2;
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerTicksBetweenThresholdAdjustment = 32;
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdInit = 3;
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdMin = 1;
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdDelta = 1;
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdSizeFactorInit = 3;
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSizeLimit = 1500;
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockAtomic32 RuntimeProfiler::state_ = 0;
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// TODO(isolates): Create the semaphore lazily and clean it up when no
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// longer required.
6444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSemaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool RuntimeProfiler::has_been_globally_setup_ = false;
688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool RuntimeProfiler::enabled_ = false;
708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockRuntimeProfiler::RuntimeProfiler(Isolate* isolate)
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_threshold_(kSamplerThresholdInit),
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_ticks_until_threshold_adjustment_(
773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          kSamplerTicksBetweenThresholdAdjustment),
783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sampler_window_position_(0) {
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ClearSampleBuffer();
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid RuntimeProfiler::GlobalSetup() {
848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!has_been_globally_setup_);
858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  enabled_ = V8::UseCrankshaft() && FLAG_opt;
868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  has_been_globally_setup_ = true;
888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid RuntimeProfiler::Optimize(JSFunction* function) {
938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(function->IsOptimizable());
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_opt) {
953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrintF("[marking ");
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
97257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" for recompilation");
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("]\n");
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The next call to the function will trigger optimization.
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  function->MarkForLazyRecompilation();
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // See AlwaysFullCompiler (in compiler.cc) comment on why we need
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Debug::has_break_points().
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(function->IsMarkedForLazyRecompilation());
11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_use_osr ||
112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate_->DebuggerHasBreakPoints() ||
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      function->IsBuiltin()) {
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedFunctionInfo* shared = function->shared();
118589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If the code is not optimizable, don't try OSR.
119589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!shared->code()->optimizable()) return;
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We are not prepared to do OSR for a function that already has an
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // allocated arguments object.  The optimized code would bypass it for
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // arguments accesses, which is unsound.  Don't try OSR.
1243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (shared->uses_arguments()) return;
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We're using on-stack replacement: patch the unoptimized code so that
127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // any back edge in any unoptimized frame will trigger on-stack
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // replacement for that frame.
129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_osr) {
130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[patching stack checks in ");
131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" for on-stack replacement]\n");
133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the stack check stub code object to match against.  We aren't
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // prepared to generate it, but we don't expect to have to.
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StackCheckStub check_stub;
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object* check_code;
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  MaybeObject* maybe_check_code = check_stub.TryGetCode();
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (maybe_check_code->ToObject(&check_code)) {
14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Code* replacement_code =
14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate_->builtins()->builtin(Builtins::kOnStackReplacement);
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Code* unoptimized_code = shared->code();
1441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Deoptimizer::PatchStackCheckCode(unoptimized_code,
1451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                     Code::cast(check_code),
1461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                     replacement_code);
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::ClearSampleBuffer() {
15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  memset(sampler_window_, 0, sizeof(sampler_window_));
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_));
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint RuntimeProfiler::LookupSample(JSFunction* function) {
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int weight = 0;
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* sample = sampler_window_[i];
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (sample != NULL) {
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (function == sample) {
16344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        weight += sampler_window_weight_[i];
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return weight;
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::AddSample(JSFunction* function, int weight) {
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsPowerOf2(kSamplerWindowSize));
17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_[sampler_window_position_] = function;
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_weight_[sampler_window_position_] = weight;
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_position_ = (sampler_window_position_ + 1) &
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (kSamplerWindowSize - 1);
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::OptimizeNow() {
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HandleScope scope(isolate_);
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the JavaScript frames and collect them. If we already
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // have a sample of the function, we mark it for optimizations
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (eagerly or lazily).
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JSFunction* samples[kSamplerFrameCount];
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int sample_count = 0;
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int frame_count = 0;
1898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (JavaScriptFrameIterator it(isolate_);
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       frame_count++ < kSamplerFrameCount && !it.done();
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       it.Advance()) {
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JavaScriptFrame* frame = it.frame();
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* function = JSFunction::cast(frame->function());
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Adjust threshold each time we have processed
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // a certain number of ticks.
19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (sampler_ticks_until_threshold_adjustment_ > 0) {
19844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_ticks_until_threshold_adjustment_--;
19944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (sampler_ticks_until_threshold_adjustment_ <= 0) {
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // If the threshold is not already at the minimum
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // modify and reset the ticks until next adjustment.
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (sampler_threshold_ > kSamplerThresholdMin) {
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sampler_threshold_ -= kSamplerThresholdDelta;
20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          sampler_ticks_until_threshold_adjustment_ =
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch              kSamplerTicksBetweenThresholdAdjustment;
206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (function->IsMarkedForLazyRecompilation()) {
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Code* unoptimized = function->shared()->code();
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int nesting = unoptimized->allow_osr_at_loop_nesting_level();
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (nesting == 0) AttemptOnStackReplacement(function);
214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Do not record non-optimizable functions.
2198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!function->IsOptimizable()) continue;
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    samples[sample_count++] = function;
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int function_size = function->shared()->SourceSize();
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int threshold_size_factor = (function_size > kSizeLimit)
22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ? sampler_threshold_size_factor_
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        : 1;
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int threshold = sampler_threshold_ * threshold_size_factor;
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (LookupSample(function) >= threshold) {
2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Optimize(function);
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Add the collected functions as samples. It's important not to do
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // this as part of collecting them because this will interfere with
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the sample lookup in case of recursive functions.
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < sample_count; i++) {
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    AddSample(samples[i], kSamplerFrameWeight[i]);
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::NotifyTick() {
24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->stack_guard()->RequestRuntimeProfilerTick();
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::Setup() {
2498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(has_been_globally_setup_);
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ClearSampleBuffer();
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the ticker hasn't already started, make sure to do so to get
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the ticks for the runtime profiler.
25344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::Reset() {
25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_threshold_ = kSamplerThresholdInit;
25944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
26044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_ticks_until_threshold_adjustment_ =
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      kSamplerTicksBetweenThresholdAdjustment;
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::TearDown() {
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Nothing to do.
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint RuntimeProfiler::SamplerWindowSize() {
271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return kSamplerWindowSize;
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Update the pointers in the sampler window after a GC.
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::UpdateSamplesAfterScavenge() {
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* function = sampler_window_[i];
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (function != NULL && isolate_->heap()->InNewSpace(function)) {
280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      MapWord map_word = HeapObject::cast(function)->map_word();
281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (map_word.IsForwardingAddress()) {
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        sampler_window_[i] = map_word.ToForwardingAddress();
283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        sampler_window_[i] = NULL;
285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
29144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The profiler thread must still be waiting.
29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(NoBarrier_Load(&state_) >= 0);
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // In IsolateEnteredJS we have already incremented the counter and
29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // undid the decrement done by the profiler thread. Increment again
29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to get the right count of active isolates.
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NoBarrier_AtomicIncrement(&state_, 1);
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  semaphore_->Signal();
29944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool RuntimeProfiler::IsSomeIsolateInJS() {
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NoBarrier_Load(&state_) > 0;
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(old_state >= -1);
31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (old_state != 0) return false;
31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  semaphore_->Wait();
31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return true;
31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
3173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Do a fake increment. If the profiler is waiting on the semaphore,
3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the returned state is 0, which can be left as an initial state in
3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // case profiling is restarted later. If the profiler is not
3203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // waiting, the increment will prevent it from waiting, but has to
3213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // be undone after the profiler is stopped.
3223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
3233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(new_state >= 0);
3243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (new_state == 0) {
3253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The profiler thread is waiting. Wake it up. It must check for
3263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // stop conditions before attempting to wait again.
3273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    semaphore_->Signal();
3283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  thread->Join();
3303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The profiler thread is now stopped. Undo the increment in case it
3313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // was not waiting.
3323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (new_state != 0) {
3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    NoBarrier_AtomicIncrement(&state_, -1);
3343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
33644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::RemoveDeadSamples() {
339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* function = sampler_window_[i];
341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (function != NULL && !HeapObject::cast(function)->IsMarked()) {
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_window_[i] = NULL;
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    visitor->VisitPointer(&sampler_window_[i]);
351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!RuntimeProfiler::IsSomeIsolateInJS()) {
3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
364