blob: 3e719cd3e1062588cafd9718f35d1d1cf288dbe6 [file] [log] [blame]
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000038#include "isolate-inl.h"
ager@chromium.org9ee27ae2011-03-02 13:43:26 +000039#include "mark-compact.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000040#include "platform.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041#include "scopeinfo.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000042
43namespace v8 {
44namespace internal {
45
46
kasperl@chromium.orga5551262010-12-07 12:49:48 +000047// Optimization sampler constants.
48static const int kSamplerFrameCount = 2;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +000049
50// Constants for statistical profiler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000051static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
kasperl@chromium.orga5551262010-12-07 12:49:48 +000052
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000053static const int kSamplerTicksBetweenThresholdAdjustment = 32;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000054
55static const int kSamplerThresholdInit = 3;
56static const int kSamplerThresholdMin = 1;
57static const int kSamplerThresholdDelta = 1;
58
59static const int kSamplerThresholdSizeFactorInit = 3;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000060
61static const int kSizeLimit = 1500;
62
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +000063// Constants for counter based profiler.
64
65// Number of times a function has to be seen on the stack before it is
66// optimized.
67static const int kProfilerTicksBeforeOptimization = 2;
68
69// Maximum size in bytes of generated code for a function to be optimized
70// the very first time it is seen on the stack.
71static const int kMaxSizeEarlyOpt = 500;
72
kasperl@chromium.orga5551262010-12-07 12:49:48 +000073
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000074Atomic32 RuntimeProfiler::state_ = 0;
75// TODO(isolates): Create the semaphore lazily and clean it up when no
76// longer required.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000077Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000078
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000079#ifdef DEBUG
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000080bool RuntimeProfiler::has_been_globally_set_up_ = false;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000081#endif
82bool RuntimeProfiler::enabled_ = false;
83
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000084
85RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
86 : isolate_(isolate),
87 sampler_threshold_(kSamplerThresholdInit),
88 sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
89 sampler_ticks_until_threshold_adjustment_(
ricow@chromium.org4f693d62011-07-04 14:01:31 +000090 kSamplerTicksBetweenThresholdAdjustment),
91 sampler_window_position_(0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000092 ClearSampleBuffer();
93}
94
95
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000096void RuntimeProfiler::GlobalSetup() {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000097 ASSERT(!has_been_globally_set_up_);
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000098 enabled_ = V8::UseCrankshaft() && FLAG_opt;
99#ifdef DEBUG
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000100 has_been_globally_set_up_ = true;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000101#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000102}
103
104
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000105void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000106 ASSERT(function->IsOptimizable());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000107 if (FLAG_trace_opt) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000108 PrintF("[marking ");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000109 function->PrintName();
danno@chromium.org160a7b02011-04-18 15:51:38 +0000110 PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000111 PrintF(" for recompilation, reason: %s", reason);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000112 PrintF("]\n");
113 }
114
115 // The next call to the function will trigger optimization.
116 function->MarkForLazyRecompilation();
117}
118
119
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000120void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 // See AlwaysFullCompiler (in compiler.cc) comment on why we need
122 // Debug::has_break_points().
123 ASSERT(function->IsMarkedForLazyRecompilation());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000124 if (!FLAG_use_osr ||
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000125 isolate_->DebuggerHasBreakPoints() ||
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000126 function->IsBuiltin()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127 return;
128 }
129
130 SharedFunctionInfo* shared = function->shared();
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000131 // If the code is not optimizable, don't try OSR.
132 if (!shared->code()->optimizable()) return;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133
134 // We are not prepared to do OSR for a function that already has an
135 // allocated arguments object. The optimized code would bypass it for
136 // arguments accesses, which is unsound. Don't try OSR.
whesse@chromium.org7b260152011-06-20 15:33:18 +0000137 if (shared->uses_arguments()) return;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000138
139 // We're using on-stack replacement: patch the unoptimized code so that
140 // any back edge in any unoptimized frame will trigger on-stack
141 // replacement for that frame.
142 if (FLAG_trace_osr) {
143 PrintF("[patching stack checks in ");
144 function->PrintName();
145 PrintF(" for on-stack replacement]\n");
146 }
147
148 // Get the stack check stub code object to match against. We aren't
149 // prepared to generate it, but we don't expect to have to.
150 StackCheckStub check_stub;
danno@chromium.orgc612e022011-11-10 11:38:15 +0000151 Code* stack_check_code = NULL;
152 if (check_stub.FindCodeInCache(&stack_check_code)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000153 Code* replacement_code =
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000154 isolate_->builtins()->builtin(Builtins::kOnStackReplacement);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 Code* unoptimized_code = shared->code();
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000156 Deoptimizer::PatchStackCheckCode(unoptimized_code,
danno@chromium.orgc612e022011-11-10 11:38:15 +0000157 stack_check_code,
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000158 replacement_code);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000159 }
160}
161
162
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000163void RuntimeProfiler::ClearSampleBuffer() {
164 memset(sampler_window_, 0, sizeof(sampler_window_));
165 memset(sampler_window_weight_, 0, sizeof(sampler_window_weight_));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000166}
167
168
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000169int RuntimeProfiler::LookupSample(JSFunction* function) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000170 int weight = 0;
171 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000172 Object* sample = sampler_window_[i];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000173 if (sample != NULL) {
174 if (function == sample) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175 weight += sampler_window_weight_[i];
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000176 }
177 }
178 }
179 return weight;
180}
181
182
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000183void RuntimeProfiler::AddSample(JSFunction* function, int weight) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000184 ASSERT(IsPowerOf2(kSamplerWindowSize));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000185 sampler_window_[sampler_window_position_] = function;
186 sampler_window_weight_[sampler_window_position_] = weight;
187 sampler_window_position_ = (sampler_window_position_ + 1) &
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000188 (kSamplerWindowSize - 1);
189}
190
191
192void RuntimeProfiler::OptimizeNow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000193 HandleScope scope(isolate_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000194
195 // Run through the JavaScript frames and collect them. If we already
196 // have a sample of the function, we mark it for optimizations
197 // (eagerly or lazily).
198 JSFunction* samples[kSamplerFrameCount];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000199 int sample_count = 0;
200 int frame_count = 0;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000201 for (JavaScriptFrameIterator it(isolate_);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000202 frame_count++ < kSamplerFrameCount && !it.done();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000203 it.Advance()) {
204 JavaScriptFrame* frame = it.frame();
205 JSFunction* function = JSFunction::cast(frame->function());
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000206
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000207 if (!FLAG_watch_ic_patching) {
208 // Adjust threshold each time we have processed
209 // a certain number of ticks.
210 if (sampler_ticks_until_threshold_adjustment_ > 0) {
211 sampler_ticks_until_threshold_adjustment_--;
212 if (sampler_ticks_until_threshold_adjustment_ <= 0) {
213 // If the threshold is not already at the minimum
214 // modify and reset the ticks until next adjustment.
215 if (sampler_threshold_ > kSamplerThresholdMin) {
216 sampler_threshold_ -= kSamplerThresholdDelta;
217 sampler_ticks_until_threshold_adjustment_ =
218 kSamplerTicksBetweenThresholdAdjustment;
219 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000220 }
221 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 }
223
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224 if (function->IsMarkedForLazyRecompilation()) {
225 Code* unoptimized = function->shared()->code();
226 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
227 if (nesting == 0) AttemptOnStackReplacement(function);
228 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
229 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000230 }
231
232 // Do not record non-optimizable functions.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000233 if (!function->IsOptimizable()) continue;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000234
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000235 if (FLAG_watch_ic_patching) {
236 int ticks = function->shared()->profiler_ticks();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000237
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000238 if (ticks >= kProfilerTicksBeforeOptimization) {
239 // If this particular function hasn't had any ICs patched for enough
240 // ticks, optimize it now.
241 Optimize(function, "hot and stable");
242 } else if (!any_ic_changed_ &&
243 function->shared()->code()->instruction_size() < kMaxSizeEarlyOpt) {
244 // If no IC was patched since the last tick and this function is very
245 // small, optimistically optimize it now.
246 Optimize(function, "small function");
247 } else if (!code_generated_ &&
248 !any_ic_changed_ &&
249 total_code_generated_ > 0 &&
250 total_code_generated_ < 2000) {
251 // If no code was generated and no IC was patched since the last tick,
252 // but a little code has already been generated since last Reset(),
253 // then type info might already be stable and we can optimize now.
254 Optimize(function, "stable on startup");
255 } else {
256 function->shared()->set_profiler_ticks(ticks + 1);
257 }
258 } else { // !FLAG_counting_profiler
259 samples[sample_count++] = function;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000260
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000261 int function_size = function->shared()->SourceSize();
262 int threshold_size_factor = (function_size > kSizeLimit)
263 ? sampler_threshold_size_factor_
264 : 1;
265
266 int threshold = sampler_threshold_ * threshold_size_factor;
267
268 if (LookupSample(function) >= threshold) {
269 Optimize(function, "sampler window lookup");
270 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000271 }
272 }
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000273 if (FLAG_watch_ic_patching) {
274 any_ic_changed_ = false;
275 code_generated_ = false;
276 } else { // !FLAG_counting_profiler
277 // Add the collected functions as samples. It's important not to do
278 // this as part of collecting them because this will interfere with
279 // the sample lookup in case of recursive functions.
280 for (int i = 0; i < sample_count; i++) {
281 AddSample(samples[i], kSamplerFrameWeight[i]);
282 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000283 }
284}
285
286
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000287void RuntimeProfiler::NotifyTick() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000288 isolate_->stack_guard()->RequestRuntimeProfilerTick();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000289}
290
291
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000292void RuntimeProfiler::SetUp() {
293 ASSERT(has_been_globally_set_up_);
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000294 if (!FLAG_watch_ic_patching) {
295 ClearSampleBuffer();
296 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000297 // If the ticker hasn't already started, make sure to do so to get
298 // the ticks for the runtime profiler.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000299 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000300}
301
302
303void RuntimeProfiler::Reset() {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000304 if (FLAG_watch_ic_patching) {
305 total_code_generated_ = 0;
306 } else { // !FLAG_counting_profiler
307 sampler_threshold_ = kSamplerThresholdInit;
308 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
309 sampler_ticks_until_threshold_adjustment_ =
310 kSamplerTicksBetweenThresholdAdjustment;
311 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000312}
313
314
315void RuntimeProfiler::TearDown() {
316 // Nothing to do.
317}
318
319
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000320int RuntimeProfiler::SamplerWindowSize() {
321 return kSamplerWindowSize;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000322}
323
324
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000325// Update the pointers in the sampler window after a GC.
326void RuntimeProfiler::UpdateSamplesAfterScavenge() {
327 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000328 Object* function = sampler_window_[i];
329 if (function != NULL && isolate_->heap()->InNewSpace(function)) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000330 MapWord map_word = HeapObject::cast(function)->map_word();
331 if (map_word.IsForwardingAddress()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000332 sampler_window_[i] = map_word.ToForwardingAddress();
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000333 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000334 sampler_window_[i] = NULL;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000335 }
336 }
337 }
338}
339
340
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000341void RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000342 // The profiler thread must still be waiting.
343 ASSERT(NoBarrier_Load(&state_) >= 0);
344 // In IsolateEnteredJS we have already incremented the counter and
345 // undid the decrement done by the profiler thread. Increment again
346 // to get the right count of active isolates.
347 NoBarrier_AtomicIncrement(&state_, 1);
348 semaphore_->Signal();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000349}
350
351
352bool RuntimeProfiler::IsSomeIsolateInJS() {
353 return NoBarrier_Load(&state_) > 0;
354}
355
356
357bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000358 Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
359 ASSERT(old_state >= -1);
360 if (old_state != 0) return false;
361 semaphore_->Wait();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000362 return true;
363}
364
365
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000366void RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000367 // Do a fake increment. If the profiler is waiting on the semaphore,
368 // the returned state is 0, which can be left as an initial state in
369 // case profiling is restarted later. If the profiler is not
370 // waiting, the increment will prevent it from waiting, but has to
371 // be undone after the profiler is stopped.
372 Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
373 ASSERT(new_state >= 0);
374 if (new_state == 0) {
375 // The profiler thread is waiting. Wake it up. It must check for
376 // stop conditions before attempting to wait again.
377 semaphore_->Signal();
378 }
379 thread->Join();
380 // The profiler thread is now stopped. Undo the increment in case it
381 // was not waiting.
382 if (new_state != 0) {
383 NoBarrier_AtomicIncrement(&state_, -1);
384 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000385}
386
387
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000388void RuntimeProfiler::RemoveDeadSamples() {
389 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000390 Object* function = sampler_window_[i];
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000391 if (function != NULL &&
392 !Marking::MarkBitFrom(HeapObject::cast(function)).Get()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000393 sampler_window_[i] = NULL;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000394 }
395 }
396}
397
398
399void RuntimeProfiler::UpdateSamplesAfterCompact(ObjectVisitor* visitor) {
400 for (int i = 0; i < kSamplerWindowSize; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000401 visitor->VisitPointer(&sampler_window_[i]);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000402 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000403}
404
405
406bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000407 if (!RuntimeProfiler::IsSomeIsolateInJS()) {
408 return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000410 return false;
411}
412
413
414} } // namespace v8::internal