Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: src/runtime-profiler.cc

Issue 6580038: [Isolates] Merge from bleeding_edge, revisions 5934-6100. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime-profiler.h ('k') | src/scanner.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 PendingListNode* next_; 65 PendingListNode* next_;
66 Handle<Object> function_; // Weak handle. 66 Handle<Object> function_; // Weak handle.
67 int64_t start_; 67 int64_t start_;
68 }; 68 };
69 69
70 70
71 // Optimization sampler constants. 71 // Optimization sampler constants.
72 static const int kSamplerFrameCount = 2; 72 static const int kSamplerFrameCount = 2;
73 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; 73 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
74 74
75 static const int kSamplerTicksDelta = 32; 75 static const int kSamplerTicksBetweenThresholdAdjustment = 32;
76 76
77 static const int kSamplerThresholdInit = 3; 77 static const int kSamplerThresholdInit = 3;
78 static const int kSamplerThresholdMin = 1; 78 static const int kSamplerThresholdMin = 1;
79 static const int kSamplerThresholdDelta = 1; 79 static const int kSamplerThresholdDelta = 1;
80 80
81 static const int kSamplerThresholdSizeFactorInit = 3; 81 static const int kSamplerThresholdSizeFactorInit = 3;
82 static const int kSamplerThresholdSizeFactorMin = 1; 82 static const int kSamplerThresholdSizeFactorMin = 1;
83 static const int kSamplerThresholdSizeFactorDelta = 1; 83 static const int kSamplerThresholdSizeFactorDelta = 1;
84 84
85 static const int kSizeLimit = 1500; 85 static const int kSizeLimit = 1500;
(...skipping 22 matching lines...) Expand all
108 108
109 static bool IsOptimizable(JSFunction* function) { 109 static bool IsOptimizable(JSFunction* function) {
110 Code* code = function->code(); 110 Code* code = function->code();
111 return code->kind() == Code::FUNCTION && code->optimizable(); 111 return code->kind() == Code::FUNCTION && code->optimizable();
112 } 112 }
113 113
114 114
115 Atomic32 RuntimeProfiler::state_ = 0; 115 Atomic32 RuntimeProfiler::state_ = 0;
116 // TODO(isolates): Create the semaphore lazily and clean it up when no 116 // TODO(isolates): Create the semaphore lazily and clean it up when no
117 // longer required. 117 // longer required.
118 #ifdef ENABLE_LOGGING_AND_PROFILING
118 Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0); 119 Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
120 #endif
119 121
120 122
121 RuntimeProfiler::RuntimeProfiler(Isolate* isolate) 123 RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
122 : isolate_(isolate), 124 : isolate_(isolate),
123 sampler_threshold_(kSamplerThresholdInit), 125 sampler_threshold_(kSamplerThresholdInit),
124 sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit), 126 sampler_threshold_size_factor_(kSamplerThresholdSizeFactorInit),
127 sampler_ticks_until_threshold_adjustment_(
128 kSamplerTicksBetweenThresholdAdjustment),
129 js_ratio_(0),
125 sampler_window_position_(0), 130 sampler_window_position_(0),
126 optimize_soon_list_(NULL) { 131 optimize_soon_list_(NULL),
132 state_window_position_(0) {
133 state_counts_[0] = kStateWindowSize;
134 state_counts_[1] = 0;
135 memset(state_window_, 0, sizeof(state_window_));
127 ClearSampleBuffer(); 136 ClearSampleBuffer();
128 } 137 }
129 138
130 139
131 bool RuntimeProfiler::IsEnabled() { 140 bool RuntimeProfiler::IsEnabled() {
132 return V8::UseCrankshaft() && FLAG_opt; 141 return V8::UseCrankshaft() && FLAG_opt;
133 } 142 }
134 143
135 144
136 void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) { 145 void RuntimeProfiler::Optimize(JSFunction* function, bool eager, int delay) {
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 } 269 }
261 delete current; 270 delete current;
262 current = next; 271 current = next;
263 } 272 }
264 optimize_soon_list_ = NULL; 273 optimize_soon_list_ = NULL;
265 274
266 // Run through the JavaScript frames and collect them. If we already 275 // Run through the JavaScript frames and collect them. If we already
267 // have a sample of the function, we mark it for optimizations 276 // have a sample of the function, we mark it for optimizations
268 // (eagerly or lazily). 277 // (eagerly or lazily).
269 JSFunction* samples[kSamplerFrameCount]; 278 JSFunction* samples[kSamplerFrameCount];
270 int count = 0; 279 int sample_count = 0;
280 int frame_count = 0;
271 for (JavaScriptFrameIterator it; 281 for (JavaScriptFrameIterator it;
272 count < kSamplerFrameCount && !it.done(); 282 frame_count++ < kSamplerFrameCount && !it.done();
273 it.Advance()) { 283 it.Advance()) {
274 JavaScriptFrame* frame = it.frame(); 284 JavaScriptFrame* frame = it.frame();
275 JSFunction* function = JSFunction::cast(frame->function()); 285 JSFunction* function = JSFunction::cast(frame->function());
276 int function_size = function->shared()->SourceSize(); 286
277 int threshold_size_factor; 287 // Adjust threshold each time we have processed
278 if (function_size > kSizeLimit) { 288 // a certain number of ticks.
279 threshold_size_factor = sampler_threshold_size_factor_; 289 if (sampler_ticks_until_threshold_adjustment_ > 0) {
280 } else { 290 sampler_ticks_until_threshold_adjustment_--;
281 threshold_size_factor = 1; 291 if (sampler_ticks_until_threshold_adjustment_ <= 0) {
292 // If the threshold is not already at the minimum
293 // modify and reset the ticks until next adjustment.
294 if (sampler_threshold_ > kSamplerThresholdMin) {
295 sampler_threshold_ -= kSamplerThresholdDelta;
296 sampler_ticks_until_threshold_adjustment_ =
297 kSamplerTicksBetweenThresholdAdjustment;
298 }
299 }
282 } 300 }
283 301
284 int threshold = sampler_threshold_ * threshold_size_factor;
285 samples[count++] = function;
286 if (function->IsMarkedForLazyRecompilation()) { 302 if (function->IsMarkedForLazyRecompilation()) {
287 Code* unoptimized = function->shared()->code(); 303 Code* unoptimized = function->shared()->code();
288 int nesting = unoptimized->allow_osr_at_loop_nesting_level(); 304 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
289 if (nesting == 0) AttemptOnStackReplacement(function); 305 if (nesting == 0) AttemptOnStackReplacement(function);
290 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); 306 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
291 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); 307 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
292 } else if (LookupSample(function) >= threshold) { 308 }
293 if (IsOptimizable(function)) { 309
294 Optimize(function, false, 0); 310 // Do not record non-optimizable functions.
295 isolate_->compilation_cache()->MarkForEagerOptimizing( 311 if (!IsOptimizable(function)) continue;
296 Handle<JSFunction>(function, isolate_)); 312 samples[sample_count++] = function;
297 } 313
314 int function_size = function->shared()->SourceSize();
315 int threshold_size_factor = (function_size > kSizeLimit)
316 ? sampler_threshold_size_factor_
317 : 1;
318
319 int threshold = sampler_threshold_ * threshold_size_factor;
320 int current_js_ratio = NoBarrier_Load(&js_ratio_);
321
322 // Adjust threshold depending on the ratio of time spent
323 // in JS code.
324 if (current_js_ratio < 20) {
325 // If we spend less than 20% of the time in JS code,
326 // do not optimize.
327 continue;
328 } else if (current_js_ratio < 75) {
329 // Below 75% of time spent in JS code, only optimize very
330 // frequently used functions.
331 threshold *= 3;
332 }
333
334 if (LookupSample(function) >= threshold) {
335 Optimize(function, false, 0);
336 isolate_->compilation_cache()->MarkForEagerOptimizing(
337 Handle<JSFunction>(function));
298 } 338 }
299 } 339 }
300 340
301 // Add the collected functions as samples. It's important not to do 341 // Add the collected functions as samples. It's important not to do
302 // this as part of collecting them because this will interfere with 342 // this as part of collecting them because this will interfere with
303 // the sample lookup in case of recursive functions. 343 // the sample lookup in case of recursive functions.
304 for (int i = 0; i < count; i++) { 344 for (int i = 0; i < sample_count; i++) {
305 AddSample(samples[i], kSamplerFrameWeight[i]); 345 AddSample(samples[i], kSamplerFrameWeight[i]);
306 } 346 }
307 } 347 }
308 348
309 349
310 void RuntimeProfiler::OptimizeSoon(JSFunction* function) { 350 void RuntimeProfiler::OptimizeSoon(JSFunction* function) {
311 if (!IsOptimizable(function)) return; 351 if (!IsOptimizable(function)) return;
312 PendingListNode* node = new PendingListNode(function); 352 PendingListNode* node = new PendingListNode(function);
313 node->set_next(optimize_soon_list_); 353 node->set_next(optimize_soon_list_);
314 optimize_soon_list_ = node; 354 optimize_soon_list_ = node;
315 } 355 }
316 356
317 357
358 #ifdef ENABLE_LOGGING_AND_PROFILING
359 void RuntimeProfiler::UpdateStateRatio(SamplerState current_state) {
360 SamplerState old_state = state_window_[state_window_position_];
361 state_counts_[old_state]--;
362 state_window_[state_window_position_] = current_state;
363 state_counts_[current_state]++;
364 ASSERT(IsPowerOf2(kStateWindowSize));
365 state_window_position_ = (state_window_position_ + 1) &
366 (kStateWindowSize - 1);
367 NoBarrier_Store(&js_ratio_, state_counts_[IN_JS_STATE] * 100 /
368 kStateWindowSize);
369 }
370 #endif
371
372
318 void RuntimeProfiler::NotifyTick() { 373 void RuntimeProfiler::NotifyTick() {
374 #ifdef ENABLE_LOGGING_AND_PROFILING
375 // Record state sample.
376 SamplerState state = IsSomeIsolateInJS()
377 ? IN_JS_STATE
378 : IN_NON_JS_STATE;
379 UpdateStateRatio(state);
319 isolate_->stack_guard()->RequestRuntimeProfilerTick(); 380 isolate_->stack_guard()->RequestRuntimeProfilerTick();
381 #endif
320 } 382 }
321 383
322 384
323 void RuntimeProfiler::MarkCompactPrologue(bool is_compacting) { 385 void RuntimeProfiler::MarkCompactPrologue(bool is_compacting) {
324 if (is_compacting) { 386 if (is_compacting) {
325 // Clear all samples before mark-sweep-compact because every 387 // Clear all samples before mark-sweep-compact because every
326 // function might move. 388 // function might move.
327 ClearSampleBuffer(); 389 ClearSampleBuffer();
328 } else { 390 } else {
329 // Clear only new space entries on mark-sweep since none of the 391 // Clear only new space entries on mark-sweep since none of the
330 // old-space functions will move. 392 // old-space functions will move.
331 ClearSampleBufferNewSpaceEntries(); 393 ClearSampleBufferNewSpaceEntries();
332 } 394 }
333 } 395 }
334 396
335 397
336 void RuntimeProfiler::Setup() { 398 void RuntimeProfiler::Setup() {
337 ClearSampleBuffer(); 399 ClearSampleBuffer();
338 // If the ticker hasn't already started, make sure to do so to get 400 // If the ticker hasn't already started, make sure to do so to get
339 // the ticks for the runtime profiler. 401 // the ticks for the runtime profiler.
340 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted(); 402 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
341 } 403 }
342 404
343 405
344 void RuntimeProfiler::Reset() { 406 void RuntimeProfiler::Reset() {
345 sampler_threshold_ = kSamplerThresholdInit; 407 sampler_threshold_ = kSamplerThresholdInit;
346 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit; 408 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
409 sampler_ticks_until_threshold_adjustment_ =
410 kSamplerTicksBetweenThresholdAdjustment;
347 } 411 }
348 412
349 413
350 void RuntimeProfiler::TearDown() { 414 void RuntimeProfiler::TearDown() {
351 // Nothing to do. 415 // Nothing to do.
352 } 416 }
353 417
354 418
355 Object** RuntimeProfiler::SamplerWindowAddress() { 419 Object** RuntimeProfiler::SamplerWindowAddress() {
356 return sampler_window_; 420 return sampler_window_;
357 } 421 }
358 422
359 423
360 int RuntimeProfiler::SamplerWindowSize() { 424 int RuntimeProfiler::SamplerWindowSize() {
361 return kSamplerWindowSize; 425 return kSamplerWindowSize;
362 } 426 }
363 427
364 428
365 void RuntimeProfiler::HandleWakeUp(Isolate* isolate) { 429 void RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
430 #ifdef ENABLE_LOGGING_AND_PROFILING
366 // The profiler thread must still be waiting. 431 // The profiler thread must still be waiting.
367 ASSERT(NoBarrier_Load(&state_) >= 0); 432 ASSERT(NoBarrier_Load(&state_) >= 0);
368 // In IsolateEnteredJS we have already incremented the counter and 433 // In IsolateEnteredJS we have already incremented the counter and
369 // undid the decrement done by the profiler thread. Increment again 434 // undid the decrement done by the profiler thread. Increment again
370 // to get the right count of active isolates. 435 // to get the right count of active isolates.
371 NoBarrier_AtomicIncrement(&state_, 1); 436 NoBarrier_AtomicIncrement(&state_, 1);
372 semaphore_->Signal(); 437 semaphore_->Signal();
373 isolate->ResetEagerOptimizingData(); 438 isolate->ResetEagerOptimizingData();
439 #endif
374 } 440 }
375 441
376 442
377 bool RuntimeProfiler::IsSomeIsolateInJS() { 443 bool RuntimeProfiler::IsSomeIsolateInJS() {
378 return NoBarrier_Load(&state_) > 0; 444 return NoBarrier_Load(&state_) > 0;
379 } 445 }
380 446
381 447
382 bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() { 448 bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
449 #ifdef ENABLE_LOGGING_AND_PROFILING
383 Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1); 450 Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
384 ASSERT(old_state >= -1); 451 ASSERT(old_state >= -1);
385 if (old_state != 0) return false; 452 if (old_state != 0) return false;
386 semaphore_->Wait(); 453 semaphore_->Wait();
454 #endif
387 return true; 455 return true;
388 } 456 }
389 457
390 458
391 void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() { 459 void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() {
460 #ifdef ENABLE_LOGGING_AND_PROFILING
392 semaphore_->Signal(); 461 semaphore_->Signal();
462 #endif
393 } 463 }
394 464
395 465
396 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() { 466 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
397 if (!RuntimeProfiler::IsEnabled()) return false; 467 #ifdef ENABLE_LOGGING_AND_PROFILING
398 static const int kNonJSTicksThreshold = 100; 468 static const int kNonJSTicksThreshold = 100;
399 if (RuntimeProfiler::IsSomeIsolateInJS()) { 469 if (RuntimeProfiler::IsSomeIsolateInJS()) {
400 non_js_ticks_ = 0; 470 non_js_ticks_ = 0;
401 } else { 471 } else {
402 if (non_js_ticks_ < kNonJSTicksThreshold) { 472 if (non_js_ticks_ < kNonJSTicksThreshold) {
403 ++non_js_ticks_; 473 ++non_js_ticks_;
404 } else { 474 } else {
405 return RuntimeProfiler::WaitForSomeIsolateToEnterJS(); 475 return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
406 } 476 }
407 } 477 }
478 #endif
408 return false; 479 return false;
409 } 480 }
410 481
411 482
412 } } // namespace v8::internal 483 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime-profiler.h ('k') | src/scanner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698