blob: 98dc00bd07a4d570d23a3dc97611d9b263a2e1da [file] [log] [blame]
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "runtime-profiler.h"
31
32#include "assembler.h"
33#include "code-stubs.h"
34#include "compilation-cache.h"
35#include "deoptimizer.h"
36#include "execution.h"
37#include "global-handles.h"
ager@chromium.org9ee27ae2011-03-02 13:43:26 +000038#include "mark-compact.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000039#include "platform.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040#include "scopeinfo.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041
42namespace v8 {
43namespace internal {
44
45
46class PendingListNode : public Malloced {
47 public:
48 explicit PendingListNode(JSFunction* function);
49 ~PendingListNode() { Destroy(); }
50
51 PendingListNode* next() const { return next_; }
52 void set_next(PendingListNode* node) { next_ = node; }
53 Handle<JSFunction> function() { return Handle<JSFunction>::cast(function_); }
54
55 // If the function is garbage collected before we've had the chance
56 // to optimize it the weak handle will be null.
57 bool IsValid() { return !function_.is_null(); }
58
59 // Returns the number of microseconds this node has been pending.
60 int Delay() const { return static_cast<int>(OS::Ticks() - start_); }
61
62 private:
63 void Destroy();
64 static void WeakCallback(v8::Persistent<v8::Value> object, void* data);
65
66 PendingListNode* next_;
67 Handle<Object> function_; // Weak handle.
68 int64_t start_;
69};
70
71
72// Optimization sampler constants.
73static const int kSamplerFrameCount = 2;
74static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000076static const int kSamplerTicksBetweenThresholdAdjustment = 32;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000077
78static const int kSamplerThresholdInit = 3;
79static const int kSamplerThresholdMin = 1;
80static const int kSamplerThresholdDelta = 1;
81
82static const int kSamplerThresholdSizeFactorInit = 3;
83static const int kSamplerThresholdSizeFactorMin = 1;
84static const int kSamplerThresholdSizeFactorDelta = 1;
85
86static const int kSizeLimit = 1500;
87
kasperl@chromium.orga5551262010-12-07 12:49:48 +000088
89PendingListNode::PendingListNode(JSFunction* function) : next_(NULL) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000090 GlobalHandles* global_handles = Isolate::Current()->global_handles();
91 function_ = global_handles->Create(function);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000092 start_ = OS::Ticks();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000093 global_handles->MakeWeak(function_.location(), this, &WeakCallback);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000094}
95
96
97void PendingListNode::Destroy() {
98 if (!IsValid()) return;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000099 GlobalHandles* global_handles = Isolate::Current()->global_handles();
100 global_handles->Destroy(function_.location());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000101 function_= Handle<Object>::null();
102}
103
104
105void PendingListNode::WeakCallback(v8::Persistent<v8::Value>, void* data) {
106 reinterpret_cast<PendingListNode*>(data)->Destroy();
107}
108
109
110static bool IsOptimizable(JSFunction* function) {
111 Code* code = function->code();
112 return code->kind() == Code::FUNCTION && code->optimizable();
113}
114
115
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000116Atomic32 RuntimeProfiler::state_ = 0;
117// TODO(isolates): Create the semaphore lazily and clean it up when no
118// longer required.
119#ifdef ENABLE_LOGGING_AND_PROFILING
120Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
121#endif
122
123
124RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
125 : isolate_(isolate),
126 sampler_threshold_(kSamplerThresholdInit),
127 sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
128 sampler_ticks_until_threshold_adjustment_(
129 kSamplerTicksBetweenThresholdAdjustment),
130 js_ratio_(0),
131 sampler_window_position_(0),
132 optimize_soon_list_(NULL),
133 state_window_position_(0) {
134 state_counts_[0] = kStateWindowSize;
135 state_counts_[1] = 0;
136 memset(state_window_, 0, sizeof(state_window_));
137 ClearSampleBuffer();
138}
139
140
141bool RuntimeProfiler::IsEnabled() {
142 return V8::UseCrankshaft() && FLAG_opt;
143}
144
145
146void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000147 ASSERT(IsOptimizable(function));
148 if (FLAG_trace_opt) {
149 PrintF("[marking (%s) ", eager ? "eagerly" : "lazily");
150 function->PrintName();
151 PrintF(" for recompilation");
152 if (delay > 0) {
153 PrintF(" (delayed %0.3f ms)", static_cast<double>(delay) / 1000);
154 }
155 PrintF("]\n");
156 }
157
158 // The next call to the function will trigger optimization.
159 function->MarkForLazyRecompilation();
160}
161
162
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000163void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000164 // See AlwaysFullCompiler (in compiler.cc) comment on why we need
165 // Debug::has_break_points().
166 ASSERT(function->IsMarkedForLazyRecompilation());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000167 if (!FLAG_use_osr ||
168 isolate_->debug()->has_break_points() ||
169 function->IsBuiltin()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000170 return;
171 }
172
173 SharedFunctionInfo* shared = function->shared();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000174 // If the code is not optimizable or references context slots, don't try OSR.
175 if (!shared->code()->optimizable() || !shared->allows_lazy_compilation()) {
176 return;
177 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000178
179 // We are not prepared to do OSR for a function that already has an
180 // allocated arguments object. The optimized code would bypass it for
181 // arguments accesses, which is unsound. Don't try OSR.
182 if (shared->scope_info()->HasArgumentsShadow()) return;
183
184 // We're using on-stack replacement: patch the unoptimized code so that
185 // any back edge in any unoptimized frame will trigger on-stack
186 // replacement for that frame.
187 if (FLAG_trace_osr) {
188 PrintF("[patching stack checks in ");
189 function->PrintName();
190 PrintF(" for on-stack replacement]\n");
191 }
192
193 // Get the stack check stub code object to match against. We aren't
194 // prepared to generate it, but we don't expect to have to.
195 StackCheckStub check_stub;
196 Object* check_code;
197 MaybeObject* maybe_check_code = check_stub.TryGetCode();
198 if (maybe_check_code->ToObject(&check_code)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 Code* replacement_code =
200 isolate_->builtins()->builtin(Builtins::OnStackReplacement);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000201 Code* unoptimized_code = shared->code();
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000202 Deoptimizer::PatchStackCheckCode(unoptimized_code,
203 Code::cast(check_code),
204 replacement_code);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000205 }
206}
207
208
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000209void RuntimeProfiler::ClearSampleBuffer() {
210 memset(sampler_window_, 0, sizeof(sampler_window_));
211 memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000212}
213
214
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000215int RuntimeProfiler::LookupSample(JSFunction* function) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000216 int weight = 0;
217 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000218 Object* sample = sampler_window_[i];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219 if (sample != NULL) {
220 if (function == sample) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000221 weight += sampler_window_weight_[i];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 }
223 }
224 }
225 return weight;
226}
227
228
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000229void RuntimeProfiler::AddSample(JSFunction* function, int weight) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000230 ASSERT(IsPowerOf2(kSamplerWindowSize));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000231 sampler_window_[sampler_window_position_] = function;
232 sampler_window_weight_[sampler_window_position_] = weight;
233 sampler_window_position_ = (sampler_window_position_ + 1) &
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000234 (kSamplerWindowSize - 1);
235}
236
237
238void RuntimeProfiler::OptimizeNow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000239 HandleScope scope(isolate_);
240 PendingListNode* current = optimize_soon_list_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241 while (current != NULL) {
242 PendingListNode* next = current->next();
243 if (current->IsValid()) {
244 Handle<JSFunction> function = current->function();
245 int delay = current->Delay();
246 if (IsOptimizable(*function)) {
247 Optimize(*function, true, delay);
248 }
249 }
250 delete current;
251 current = next;
252 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000253 optimize_soon_list_ = NULL;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000254
255 // Run through the JavaScript frames and collect them. If we already
256 // have a sample of the function, we mark it for optimizations
257 // (eagerly or lazily).
258 JSFunction* samples[kSamplerFrameCount];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000259 int sample_count = 0;
260 int frame_count = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000261 for (JavaScriptFrameIterator it;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000262 frame_count++ < kSamplerFrameCount && !it.done();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000263 it.Advance()) {
264 JavaScriptFrame* frame = it.frame();
265 JSFunction* function = JSFunction::cast(frame->function());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000266
267 // Adjust threshold each time we have processed
268 // a certain number of ticks.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000269 if (sampler_ticks_until_threshold_adjustment_ > 0) {
270 sampler_ticks_until_threshold_adjustment_--;
271 if (sampler_ticks_until_threshold_adjustment_ <= 0) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000272 // If the threshold is not already at the minimum
273 // modify and reset the ticks until next adjustment.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000274 if (sampler_threshold_ > kSamplerThresholdMin) {
275 sampler_threshold_ -= kSamplerThresholdDelta;
276 sampler_ticks_until_threshold_adjustment_ =
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000277 kSamplerTicksBetweenThresholdAdjustment;
278 }
279 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000280 }
281
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000282 if (function->IsMarkedForLazyRecompilation()) {
283 Code* unoptimized = function->shared()->code();
284 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
285 if (nesting == 0) AttemptOnStackReplacement(function);
286 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
287 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000288 }
289
290 // Do not record non-optimizable functions.
291 if (!IsOptimizable(function)) continue;
292 samples[sample_count++] = function;
293
294 int function_size = function->shared()->SourceSize();
295 int threshold_size_factor = (function_size > kSizeLimit)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000296 ? sampler_threshold_size_factor_
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000297 : 1;
298
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 int threshold = sampler_threshold_ * threshold_size_factor;
300 int current_js_ratio = NoBarrier_Load(&js_ratio_);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000301
302 // Adjust threshold depending on the ratio of time spent
303 // in JS code.
304 if (current_js_ratio < 20) {
305 // If we spend less than 20% of the time in JS code,
306 // do not optimize.
307 continue;
308 } else if (current_js_ratio < 75) {
309 // Below 75% of time spent in JS code, only optimize very
310 // frequently used functions.
311 threshold *= 3;
312 }
313
314 if (LookupSample(function) >= threshold) {
315 Optimize(function, false, 0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000316 isolate_->compilation_cache()->MarkForEagerOptimizing(
317 Handle<JSFunction>(function));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000318 }
319 }
320
321 // Add the collected functions as samples. It's important not to do
322 // this as part of collecting them because this will interfere with
323 // the sample lookup in case of recursive functions.
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000324 for (int i = 0; i < sample_count; i++) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 AddSample(samples[i], kSamplerFrameWeight[i]);
326 }
327}
328
329
330void RuntimeProfiler::OptimizeSoon(JSFunction* function) {
331 if (!IsOptimizable(function)) return;
332 PendingListNode* node = new PendingListNode(function);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000333 node->set_next(optimize_soon_list_);
334 optimize_soon_list_ = node;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000335}
336
337
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000338#ifdef ENABLE_LOGGING_AND_PROFILING
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000339void RuntimeProfiler::UpdateStateRatio(SamplerState current_state) {
340 SamplerState old_state = state_window_[state_window_position_];
341 state_counts_[old_state]--;
342 state_window_[state_window_position_] = current_state;
343 state_counts_[current_state]++;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000344 ASSERT(IsPowerOf2(kStateWindowSize));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345 state_window_position_ = (state_window_position_ + 1) &
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000346 (kStateWindowSize - 1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000347 NoBarrier_Store(&js_ratio_, state_counts_[IN_JS_STATE] * 100 /
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000348 kStateWindowSize);
349}
350#endif
351
352
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000353void RuntimeProfiler::NotifyTick() {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000354#ifdef ENABLE_LOGGING_AND_PROFILING
355 // Record state sample.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000356 SamplerState state = IsSomeIsolateInJS()
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000357 ? IN_JS_STATE
358 : IN_NON_JS_STATE;
359 UpdateStateRatio(state);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000360 isolate_->stack_guard()->RequestRuntimeProfilerTick();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000361#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000362}
363
364
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000365void RuntimeProfiler::Setup() {
366 ClearSampleBuffer();
367 // If the ticker hasn't already started, make sure to do so to get
368 // the ticks for the runtime profiler.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000369 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000370}
371
372
373void RuntimeProfiler::Reset() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000374 sampler_threshold_ = kSamplerThresholdInit;
375 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
376 sampler_ticks_until_threshold_adjustment_ =
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000377 kSamplerTicksBetweenThresholdAdjustment;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000378}
379
380
381void RuntimeProfiler::TearDown() {
382 // Nothing to do.
383}
384
385
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000386int RuntimeProfiler::SamplerWindowSize() {
387 return kSamplerWindowSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000388}
389
390
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000391// Update the pointers in the sampler window after a GC.
392void RuntimeProfiler::UpdateSamplesAfterScavenge() {
393 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000394 Object* function = sampler_window_[i];
395 if (function != NULL && isolate_->heap()->InNewSpace(function)) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000396 MapWord map_word = HeapObject::cast(function)->map_word();
397 if (map_word.IsForwardingAddress()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000398 sampler_window_[i] = map_word.ToForwardingAddress();
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000399 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000400 sampler_window_[i] = NULL;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000401 }
402 }
403 }
404}
405
406
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000407void RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
408#ifdef ENABLE_LOGGING_AND_PROFILING
409 // The profiler thread must still be waiting.
410 ASSERT(NoBarrier_Load(&state_) >= 0);
411 // In IsolateEnteredJS we have already incremented the counter and
412 // undid the decrement done by the profiler thread. Increment again
413 // to get the right count of active isolates.
414 NoBarrier_AtomicIncrement(&state_, 1);
415 semaphore_->Signal();
416 isolate->ResetEagerOptimizingData();
417#endif
418}
419
420
421bool RuntimeProfiler::IsSomeIsolateInJS() {
422 return NoBarrier_Load(&state_) > 0;
423}
424
425
426bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
427#ifdef ENABLE_LOGGING_AND_PROFILING
428 Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
429 ASSERT(old_state >= -1);
430 if (old_state != 0) return false;
431 semaphore_->Wait();
432#endif
433 return true;
434}
435
436
437void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() {
438#ifdef ENABLE_LOGGING_AND_PROFILING
439 semaphore_->Signal();
440#endif
441}
442
443
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000444void RuntimeProfiler::RemoveDeadSamples() {
445 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000446 Object* function = sampler_window_[i];
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000447 if (function != NULL && !HeapObject::cast(function)->IsMarked()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000448 sampler_window_[i] = NULL;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000449 }
450 }
451}
452
453
454void RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
455 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000456 visitor->VisitPointer(&sampler_window_[i]);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000457 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000458}
459
460
461bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000462#ifdef ENABLE_LOGGING_AND_PROFILING
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000463 static const int kNonJSTicksThreshold = 100;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000464 if (RuntimeProfiler::IsSomeIsolateInJS()) {
465 non_js_ticks_ = 0;
466 } else {
467 if (non_js_ticks_ < kNonJSTicksThreshold) {
468 ++non_js_ticks_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000469 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000470 return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000471 }
472 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000473#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000474 return false;
475}
476
477
478} } // namespace v8::internal