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

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

Issue 9361026: Count-based profiling for primitive functions (hidden behind a flag) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: more comments Created 8 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/x64/full-codegen-x64.cc » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2012 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
11 // with the distribution. 11 // with the distribution.
(...skipping 27 matching lines...) Expand all
39 #include "mark-compact.h" 39 #include "mark-compact.h"
40 #include "platform.h" 40 #include "platform.h"
41 #include "scopeinfo.h" 41 #include "scopeinfo.h"
42 42
43 namespace v8 { 43 namespace v8 {
44 namespace internal { 44 namespace internal {
45 45
46 46
47 // Optimization sampler constants. 47 // Optimization sampler constants.
48 static const int kSamplerFrameCount = 2; 48 static const int kSamplerFrameCount = 2;
49
50 // Constants for statistical profiler.
49 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; 51 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
50 52
51 static const int kSamplerTicksBetweenThresholdAdjustment = 32; 53 static const int kSamplerTicksBetweenThresholdAdjustment = 32;
52 54
53 static const int kSamplerThresholdInit = 3; 55 static const int kSamplerThresholdInit = 3;
54 static const int kSamplerThresholdMin = 1; 56 static const int kSamplerThresholdMin = 1;
55 static const int kSamplerThresholdDelta = 1; 57 static const int kSamplerThresholdDelta = 1;
56 58
57 static const int kSamplerThresholdSizeFactorInit = 3; 59 static const int kSamplerThresholdSizeFactorInit = 3;
58 60
59 static const int kSizeLimit = 1500; 61 static const int kSizeLimit = 1500;
60 62
63 // Constants for counter based profiler.
64
65 // Number of times a function has to be seen on the stack before it is
66 // optimized.
67 static 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.
71 static const int kMaxSizeEarlyOpt = 500;
72
61 73
62 Atomic32 RuntimeProfiler::state_ = 0; 74 Atomic32 RuntimeProfiler::state_ = 0;
63 // TODO(isolates): Create the semaphore lazily and clean it up when no 75 // TODO(isolates): Create the semaphore lazily and clean it up when no
64 // longer required. 76 // longer required.
65 Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0); 77 Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0);
66 78
67 #ifdef DEBUG 79 #ifdef DEBUG
68 bool RuntimeProfiler::has_been_globally_set_up_ = false; 80 bool RuntimeProfiler::has_been_globally_set_up_ = false;
69 #endif 81 #endif
70 bool RuntimeProfiler::enabled_ = false; 82 bool RuntimeProfiler::enabled_ = false;
(...skipping 12 matching lines...) Expand all
83 95
84 void RuntimeProfiler::GlobalSetup() { 96 void RuntimeProfiler::GlobalSetup() {
85 ASSERT(!has_been_globally_set_up_); 97 ASSERT(!has_been_globally_set_up_);
86 enabled_ = V8::UseCrankshaft() && FLAG_opt; 98 enabled_ = V8::UseCrankshaft() && FLAG_opt;
87 #ifdef DEBUG 99 #ifdef DEBUG
88 has_been_globally_set_up_ = true; 100 has_been_globally_set_up_ = true;
89 #endif 101 #endif
90 } 102 }
91 103
92 104
93 void RuntimeProfiler::Optimize(JSFunction* function) { 105 void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
94 ASSERT(function->IsOptimizable()); 106 ASSERT(function->IsOptimizable());
95 if (FLAG_trace_opt) { 107 if (FLAG_trace_opt) {
96 PrintF("[marking "); 108 PrintF("[marking ");
97 function->PrintName(); 109 function->PrintName();
98 PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address())); 110 PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
99 PrintF(" for recompilation"); 111 PrintF(" for recompilation, reason: %s", reason);
100 PrintF("]\n"); 112 PrintF("]\n");
101 } 113 }
102 114
103 // The next call to the function will trigger optimization. 115 // The next call to the function will trigger optimization.
104 function->MarkForLazyRecompilation(); 116 function->MarkForLazyRecompilation();
105 } 117 }
106 118
107 119
108 void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) { 120 void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
109 // See AlwaysFullCompiler (in compiler.cc) comment on why we need 121 // See AlwaysFullCompiler (in compiler.cc) comment on why we need
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // (eagerly or lazily). 197 // (eagerly or lazily).
186 JSFunction* samples[kSamplerFrameCount]; 198 JSFunction* samples[kSamplerFrameCount];
187 int sample_count = 0; 199 int sample_count = 0;
188 int frame_count = 0; 200 int frame_count = 0;
189 for (JavaScriptFrameIterator it(isolate_); 201 for (JavaScriptFrameIterator it(isolate_);
190 frame_count++ < kSamplerFrameCount && !it.done(); 202 frame_count++ < kSamplerFrameCount && !it.done();
191 it.Advance()) { 203 it.Advance()) {
192 JavaScriptFrame* frame = it.frame(); 204 JavaScriptFrame* frame = it.frame();
193 JSFunction* function = JSFunction::cast(frame->function()); 205 JSFunction* function = JSFunction::cast(frame->function());
194 206
195 // Adjust threshold each time we have processed 207 if (!FLAG_counting_profiler) {
196 // a certain number of ticks. 208 // Adjust threshold each time we have processed
197 if (sampler_ticks_until_threshold_adjustment_ > 0) { 209 // a certain number of ticks.
198 sampler_ticks_until_threshold_adjustment_--; 210 if (sampler_ticks_until_threshold_adjustment_ > 0) {
199 if (sampler_ticks_until_threshold_adjustment_ <= 0) { 211 sampler_ticks_until_threshold_adjustment_--;
200 // If the threshold is not already at the minimum 212 if (sampler_ticks_until_threshold_adjustment_ <= 0) {
201 // modify and reset the ticks until next adjustment. 213 // If the threshold is not already at the minimum
202 if (sampler_threshold_ > kSamplerThresholdMin) { 214 // modify and reset the ticks until next adjustment.
203 sampler_threshold_ -= kSamplerThresholdDelta; 215 if (sampler_threshold_ > kSamplerThresholdMin) {
204 sampler_ticks_until_threshold_adjustment_ = 216 sampler_threshold_ -= kSamplerThresholdDelta;
205 kSamplerTicksBetweenThresholdAdjustment; 217 sampler_ticks_until_threshold_adjustment_ =
218 kSamplerTicksBetweenThresholdAdjustment;
219 }
206 } 220 }
207 } 221 }
208 } 222 }
209 223
210 if (function->IsMarkedForLazyRecompilation()) { 224 if (function->IsMarkedForLazyRecompilation()) {
211 Code* unoptimized = function->shared()->code(); 225 Code* unoptimized = function->shared()->code();
212 int nesting = unoptimized->allow_osr_at_loop_nesting_level(); 226 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
213 if (nesting == 0) AttemptOnStackReplacement(function); 227 if (nesting == 0) AttemptOnStackReplacement(function);
214 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); 228 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
215 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); 229 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
216 } 230 }
217 231
218 // Do not record non-optimizable functions. 232 // Do not record non-optimizable functions.
219 if (!function->IsOptimizable()) continue; 233 if (!function->IsOptimizable()) continue;
220 samples[sample_count++] = function;
221 234
222 int function_size = function->shared()->SourceSize(); 235 if (FLAG_counting_profiler) {
223 int threshold_size_factor = (function_size > kSizeLimit) 236 int ticks = function->shared()->profiler_ticks();
224 ? sampler_threshold_size_factor_
225 : 1;
226 237
227 int threshold = sampler_threshold_ * threshold_size_factor; 238 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;
228 260
229 if (LookupSample(function) >= threshold) { 261 int function_size = function->shared()->SourceSize();
230 Optimize(function); 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 }
231 } 271 }
232 } 272 }
233 273 if (FLAG_counting_profiler) {
234 // Add the collected functions as samples. It's important not to do 274 any_ic_changed_ = false;
235 // this as part of collecting them because this will interfere with 275 code_generated_ = false;
236 // the sample lookup in case of recursive functions. 276 } else { // !FLAG_counting_profiler
237 for (int i = 0; i < sample_count; i++) { 277 // Add the collected functions as samples. It's important not to do
238 AddSample(samples[i], kSamplerFrameWeight[i]); 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 }
239 } 283 }
240 } 284 }
241 285
242 286
243 void RuntimeProfiler::NotifyTick() { 287 void RuntimeProfiler::NotifyTick() {
244 isolate_->stack_guard()->RequestRuntimeProfilerTick(); 288 isolate_->stack_guard()->RequestRuntimeProfilerTick();
245 } 289 }
246 290
247 291
248 void RuntimeProfiler::SetUp() { 292 void RuntimeProfiler::SetUp() {
249 ASSERT(has_been_globally_set_up_); 293 ASSERT(has_been_globally_set_up_);
250 ClearSampleBuffer(); 294 if (!FLAG_counting_profiler) {
295 ClearSampleBuffer();
296 }
251 // If the ticker hasn't already started, make sure to do so to get 297 // If the ticker hasn't already started, make sure to do so to get
252 // the ticks for the runtime profiler. 298 // the ticks for the runtime profiler.
253 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted(); 299 if (IsEnabled()) isolate_->logger()->EnsureTickerStarted();
254 } 300 }
255 301
256 302
257 void RuntimeProfiler::Reset() { 303 void RuntimeProfiler::Reset() {
258 sampler_threshold_ = kSamplerThresholdInit; 304 if (FLAG_counting_profiler) {
259 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit; 305 total_code_generated_ = 0;
260 sampler_ticks_until_threshold_adjustment_ = 306 } else { // !FLAG_counting_profiler
261 kSamplerTicksBetweenThresholdAdjustment; 307 sampler_threshold_ = kSamplerThresholdInit;
308 sampler_threshold_size_factor_ = kSamplerThresholdSizeFactorInit;
309 sampler_ticks_until_threshold_adjustment_ =
310 kSamplerTicksBetweenThresholdAdjustment;
311 }
262 } 312 }
263 313
264 314
265 void RuntimeProfiler::TearDown() { 315 void RuntimeProfiler::TearDown() {
266 // Nothing to do. 316 // Nothing to do.
267 } 317 }
268 318
269 319
270 int RuntimeProfiler::SamplerWindowSize() { 320 int RuntimeProfiler::SamplerWindowSize() {
271 return kSamplerWindowSize; 321 return kSamplerWindowSize;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 405
356 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() { 406 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
357 if (!RuntimeProfiler::IsSomeIsolateInJS()) { 407 if (!RuntimeProfiler::IsSomeIsolateInJS()) {
358 return RuntimeProfiler::WaitForSomeIsolateToEnterJS(); 408 return RuntimeProfiler::WaitForSomeIsolateToEnterJS();
359 } 409 }
360 return false; 410 return false;
361 } 411 }
362 412
363 413
364 } } // namespace v8::internal 414 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime-profiler.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698