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