13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 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"
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "isolate-inl.h"
39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "mark-compact.h"
4044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "platform.h"
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopeinfo.h"
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Optimization sampler constants.
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerFrameCount = 2;
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Constants for statistical profiler.
51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerTicksBetweenThresholdAdjustment = 32;
54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdInit = 3;
56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdMin = 1;
57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdDelta = 1;
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSamplerThresholdSizeFactorInit = 3;
60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const int kSizeLimit = 1500;
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Constants for counter based profiler.
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Number of times a function has to be seen on the stack before it is
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// optimized.
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kProfilerTicksBeforeOptimization = 2;
688f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch// If a function does not have enough type info (according to
698f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch// FLAG_type_info_threshold), but has seen a huge number of ticks,
708f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch// optimize it as it is.
718f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdochstatic const int kTicksWhenNotEnoughTypeInfo = 100;
728f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch// We only have one byte to store the number of ticks.
738f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben MurdochSTATIC_ASSERT(kTicksWhenNotEnoughTypeInfo < 256);
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Maximum size in bytes of generated code for a function to be optimized
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the very first time it is seen on the stack.
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int kMaxSizeEarlyOpt = 500;
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockAtomic32 RuntimeProfiler::state_ = 0;
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// TODO(isolates): Clean up the semaphore when it is no longer required.
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic LazySemaphore<0>::type semaphore = LAZY_SEMAPHORE_INITIALIZER;
8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool RuntimeProfiler::has_been_globally_set_up_ = false;
878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool RuntimeProfiler::enabled_ = false;
898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockRuntimeProfiler::RuntimeProfiler(Isolate* isolate)
9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_threshold_(kSamplerThresholdInit),
9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_ticks_until_threshold_adjustment_(
963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          kSamplerTicksBetweenThresholdAdjustment),
973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sampler_window_position_(0) {
9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ClearSampleBuffer();
9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid RuntimeProfiler::GlobalSetup() {
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!has_been_globally_set_up_);
1048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  enabled_ = V8::UseCrankshaft() && FLAG_opt;
1058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  has_been_globally_set_up_ = true;
1078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GetICCounts(JSFunction* function,
1128f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch                        int* ic_with_type_info_count,
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        int* ic_total_count,
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        int* percentage) {
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *ic_total_count = 0;
1168f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  *ic_with_type_info_count = 0;
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* raw_info =
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function->shared()->code()->type_feedback_info();
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_info->IsTypeFeedbackInfo()) {
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info);
1218f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    *ic_with_type_info_count = info->ic_with_type_info_count();
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *ic_total_count = info->ic_total_count();
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *percentage = *ic_total_count > 0
1258f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      ? 100 * *ic_with_type_info_count / *ic_total_count
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : 100;
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
1318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(function->IsOptimizable());
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_opt) {
1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrintF("[marking ");
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF(" for recompilation, reason: %s", reason);
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_type_info_threshold > 0) {
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int typeinfo, total, percentage;
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetICCounts(function, &typeinfo, &total, &percentage);
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total, percentage);
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("]\n");
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The next call to the function will trigger optimization.
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  function->MarkForLazyRecompilation();
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
15044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // See AlwaysFullCompiler (in compiler.cc) comment on why we need
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Debug::has_break_points().
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(function->IsMarkedForLazyRecompilation());
15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (!FLAG_use_osr ||
155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      isolate_->DebuggerHasBreakPoints() ||
15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      function->IsBuiltin()) {
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  SharedFunctionInfo* shared = function->shared();
161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // If the code is not optimizable, don't try OSR.
162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (!shared->code()->optimizable()) return;
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We are not prepared to do OSR for a function that already has an
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // allocated arguments object.  The optimized code would bypass it for
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // arguments accesses, which is unsound.  Don't try OSR.
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (shared->uses_arguments()) return;
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We're using on-stack replacement: patch the unoptimized code so that
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // any back edge in any unoptimized frame will trigger on-stack
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // replacement for that frame.
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_osr) {
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[patching stack checks in ");
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" for on-stack replacement]\n");
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the stack check stub code object to match against.  We aren't
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // prepared to generate it, but we don't expect to have to.
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool found_code = false;
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Code* stack_check_code = NULL;
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if defined(V8_TARGET_ARCH_IA32) || \
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    defined(V8_TARGET_ARCH_ARM) || \
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    defined(V8_TARGET_ARCH_MIPS)
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) {
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InterruptStub interrupt_stub;
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    found_code = interrupt_stub.FindCodeInCache(&stack_check_code);
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else  // NOLINT
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {  // NOLINT
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    StackCheckStub check_stub;
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    found_code = check_stub.FindCodeInCache(&stack_check_code);
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (found_code) {
19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Code* replacement_code =
19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate_->builtins()->builtin(Builtins::kOnStackReplacement);
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Code* unoptimized_code = shared->code();
1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Deoptimizer::PatchStackCheckCode(unoptimized_code,
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     stack_check_code,
2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                     replacement_code);
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
20544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::ClearSampleBuffer() {
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  memset(sampler_window_, 0, sizeof(sampler_window_));
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_));
208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
21144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint RuntimeProfiler::LookupSample(JSFunction* function) {
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int weight = 0;
213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* sample = sampler_window_[i];
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (sample != NULL) {
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (function == sample) {
21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        weight += sampler_window_weight_[i];
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return weight;
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
22544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::AddSample(JSFunction* function, int weight) {
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(IsPowerOf2(kSamplerWindowSize));
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_[sampler_window_position_] = function;
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_weight_[sampler_window_position_] = weight;
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sampler_window_position_ = (sampler_window_position_ + 1) &
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      (kSamplerWindowSize - 1);
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::OptimizeNow() {
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HandleScope scope(isolate_);
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the JavaScript frames and collect them. If we already
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // have a sample of the function, we mark it for optimizations
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // (eagerly or lazily).
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JSFunction* samples[kSamplerFrameCount];
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int sample_count = 0;
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int frame_count = 0;
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int frame_count_limit = FLAG_watch_ic_patching ? FLAG_frame_count
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 : kSamplerFrameCount;
2458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (JavaScriptFrameIterator it(isolate_);
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       frame_count++ < frame_count_limit && !it.done();
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       it.Advance()) {
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JavaScriptFrame* frame = it.frame();
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* function = JSFunction::cast(frame->function());
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!FLAG_watch_ic_patching) {
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Adjust threshold each time we have processed
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // a certain number of ticks.
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (sampler_ticks_until_threshold_adjustment_ > 0) {
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        sampler_ticks_until_threshold_adjustment_--;
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (sampler_ticks_until_threshold_adjustment_ <= 0) {
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // If the threshold is not already at the minimum
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // modify and reset the ticks until next adjustment.
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (sampler_threshold_ > kSamplerThresholdMin) {
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            sampler_threshold_ -= kSamplerThresholdDelta;
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            sampler_ticks_until_threshold_adjustment_ =
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                kSamplerTicksBetweenThresholdAdjustment;
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2688f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    Code* shared_code = function->shared()->code();
2698f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    if (shared_code->kind() != Code::FUNCTION) continue;
2708f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch
2718f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch    if (function->IsMarkedForLazyRecompilation()) {
2728f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      int nesting = shared_code->allow_osr_at_loop_nesting_level();
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (nesting == 0) AttemptOnStackReplacement(function);
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
2758f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      shared_code->set_allow_osr_at_loop_nesting_level(new_nesting);
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Do not record non-optimizable functions.
2798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (!function->IsOptimizable()) continue;
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (function->shared()->optimization_disabled()) continue;
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Only record top-level code on top of the execution stack and
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // avoid optimizing excessively large scripts since top-level code
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // will be executed only once.
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const int kMaxToplevelSourceSize = 10 * 1024;
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (function->shared()->is_toplevel()
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        && (frame_count > 1
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            || function->shared()->SourceSize() > kMaxToplevelSourceSize)) {
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      continue;
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_watch_ic_patching) {
2938f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch      int ticks = shared_code->profiler_ticks();
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (ticks >= kProfilerTicksBeforeOptimization) {
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int typeinfo, total, percentage;
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        GetICCounts(function, &typeinfo, &total, &percentage);
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (percentage >= FLAG_type_info_threshold) {
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // If this particular function hasn't had any ICs patched for enough
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // ticks, optimize it now.
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Optimize(function, "hot and stable");
3028f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        } else if (ticks >= kTicksWhenNotEnoughTypeInfo) {
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Optimize(function, "not much type info but very hot");
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
3058f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch          shared_code->set_profiler_ticks(ticks + 1);
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (FLAG_trace_opt_verbose) {
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            PrintF("[not yet optimizing ");
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            function->PrintName();
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            PrintF(", not enough type info: %d/%d (%d%%)]\n",
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                   typeinfo, total, percentage);
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (!any_ic_changed_ &&
3148f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch          shared_code->instruction_size() < kMaxSizeEarlyOpt) {
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If no IC was patched since the last tick and this function is very
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // small, optimistically optimize it now.
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Optimize(function, "small function");
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (!code_generated_ &&
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          !any_ic_changed_ &&
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          total_code_generated_ > 0 &&
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          total_code_generated_ < 2000) {
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If no code was generated and no IC was patched since the last tick,
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // but a little code has already been generated since last Reset(),
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // then type info might already be stable and we can optimize now.
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Optimize(function, "stable on startup");
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
3278f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch        shared_code->set_profiler_ticks(ticks + 1);
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {  // !FLAG_watch_ic_patching
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      samples[sample_count++] = function;
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int function_size = function->shared()->SourceSize();
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int threshold_size_factor = (function_size > kSizeLimit)
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ? sampler_threshold_size_factor_
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          : 1;
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      int threshold = sampler_threshold_ * threshold_size_factor;
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (LookupSample(function) >= threshold) {
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Optimize(function, "sampler window lookup");
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_watch_ic_patching) {
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    any_ic_changed_ = false;
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    code_generated_ = false;
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // !FLAG_watch_ic_patching
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Add the collected functions as samples. It's important not to do
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // this as part of collecting them because this will interfere with
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // the sample lookup in case of recursive functions.
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < sample_count; i++) {
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      AddSample(samples[i], kSamplerFrameWeight[i]);
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::NotifyTick() {
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if defined(V8_TARGET_ARCH_IA32) || \
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    defined(V8_TARGET_ARCH_ARM) || \
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    defined(V8_TARGET_ARCH_MIPS)
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_count_based_interrupts) return;
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->stack_guard()->RequestRuntimeProfilerTick();
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid RuntimeProfiler::SetUp() {
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(has_been_globally_set_up_);
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_watch_ic_patching) {
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ClearSampleBuffer();
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // If the ticker hasn't already started, make sure to do so to get
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the ticks for the runtime profiler.
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::Reset() {
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_watch_ic_patching) {
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    total_code_generated_ = 0;
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {  // !FLAG_watch_ic_patching
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sampler_threshold_ = kSamplerThresholdInit;
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    sampler_ticks_until_threshold_adjustment_ =
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        kSamplerTicksBetweenThresholdAdjustment;
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid RuntimeProfiler::TearDown() {
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Nothing to do.
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint RuntimeProfiler::SamplerWindowSize() {
397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return kSamplerWindowSize;
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Update the pointers in the sampler window after a GC.
402e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::UpdateSamplesAfterScavenge() {
403e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* function = sampler_window_[i];
40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (function != NULL && isolate_->heap()->InNewSpace(function)) {
406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      MapWord map_word = HeapObject::cast(function)->map_word();
407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (map_word.IsForwardingAddress()) {
40844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        sampler_window_[i] = map_word.ToForwardingAddress();
409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
41044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        sampler_window_[i] = NULL;
411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
41744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // The profiler thread must still be waiting.
41944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(NoBarrier_Load(&state_) >= 0);
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // In IsolateEnteredJS we have already incremented the counter and
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // undid the decrement done by the profiler thread. Increment again
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // to get the right count of active isolates.
42344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  NoBarrier_AtomicIncrement(&state_, 1);
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  semaphore.Pointer()->Signal();
42544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
42644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
42844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool RuntimeProfiler::IsSomeIsolateInJS() {
42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NoBarrier_Load(&state_) > 0;
43044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
43144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
43344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(old_state >= -1);
43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (old_state != 0) return false;
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  semaphore.Pointer()->Wait();
43844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return true;
43944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
4433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Do a fake increment. If the profiler is waiting on the semaphore,
4443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // the returned state is 0, which can be left as an initial state in
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // case profiling is restarted later. If the profiler is not
4463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // waiting, the increment will prevent it from waiting, but has to
4473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // be undone after the profiler is stopped.
4483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
4493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(new_state >= 0);
4503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (new_state == 0) {
4513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // The profiler thread is waiting. Wake it up. It must check for
4523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // stop conditions before attempting to wait again.
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    semaphore.Pointer()->Signal();
4543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  thread->Join();
4563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // The profiler thread is now stopped. Undo the increment in case it
4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // was not waiting.
4583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (new_state != 0) {
4593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    NoBarrier_AtomicIncrement(&state_, -1);
4603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::RemoveDeadSamples() {
465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Object* function = sampler_window_[i];
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (function != NULL &&
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !Marking::MarkBitFrom(HeapObject::cast(function)).Get()) {
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      sampler_window_[i] = NULL;
470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < kSamplerWindowSize; i++) {
47744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    visitor->VisitPointer(&sampler_window_[i]);
478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!RuntimeProfiler::IsSomeIsolateInJS()) {
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return false;
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
491