OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime-profiler.h" | 5 #include "src/runtime-profiler.h" |
6 | 6 |
7 #include "src/assembler.h" | 7 #include "src/assembler.h" |
8 #include "src/ast/scopeinfo.h" | 8 #include "src/ast/scopeinfo.h" |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total, | 103 PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total, |
104 type_percentage); | 104 type_percentage); |
105 PrintF(", generic ICs: %d/%d (%d%%)", generic, total, generic_percentage); | 105 PrintF(", generic ICs: %d/%d (%d%%)", generic, total, generic_percentage); |
106 } | 106 } |
107 PrintF("]\n"); | 107 PrintF("]\n"); |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) { | 111 void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) { |
112 TraceRecompile(function, reason, "optimized"); | 112 TraceRecompile(function, reason, "optimized"); |
113 | |
114 // TODO(4280): Fix this to check function is compiled to baseline once we | |
115 // have a standard way to check that. For now, if baseline code doesn't have | |
116 // a bytecode array. | |
117 DCHECK(!function->shared()->HasBytecodeArray()); | |
118 function->AttemptConcurrentOptimization(); | 113 function->AttemptConcurrentOptimization(); |
119 } | 114 } |
120 | 115 |
121 void RuntimeProfiler::Baseline(JSFunction* function, const char* reason) { | 116 void RuntimeProfiler::Baseline(JSFunction* function, const char* reason) { |
122 TraceRecompile(function, reason, "baseline"); | 117 TraceRecompile(function, reason, "baseline"); |
123 | 118 |
124 // TODO(4280): Fix this to check function is compiled for the interpreter | 119 // TODO(4280): Fix this to check function is compiled for the interpreter |
125 // once we have a standard way to check that. For now function will only | 120 // once we have a standard way to check that. For now function will only |
126 // have a bytecode array if compiled for the interpreter. | 121 // have a bytecode array if compiled for the interpreter. |
127 DCHECK(function->shared()->HasBytecodeArray()); | 122 DCHECK(function->shared()->HasBytecodeArray()); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 generic_percentage <= FLAG_generic_ic_threshold) { | 241 generic_percentage <= FLAG_generic_ic_threshold) { |
247 Optimize(function, "small function"); | 242 Optimize(function, "small function"); |
248 } else { | 243 } else { |
249 shared_code->set_profiler_ticks(ticks + 1); | 244 shared_code->set_profiler_ticks(ticks + 1); |
250 } | 245 } |
251 } else { | 246 } else { |
252 shared_code->set_profiler_ticks(ticks + 1); | 247 shared_code->set_profiler_ticks(ticks + 1); |
253 } | 248 } |
254 } | 249 } |
255 | 250 |
256 void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function) { | 251 void RuntimeProfiler::MaybeBaselineIgnition(JSFunction* function) { |
257 if (function->IsInOptimizationQueue()) return; | 252 if (function->IsInOptimizationQueue()) return; |
258 | 253 |
259 SharedFunctionInfo* shared = function->shared(); | 254 SharedFunctionInfo* shared = function->shared(); |
260 int ticks = shared->profiler_ticks(); | 255 int ticks = shared->profiler_ticks(); |
261 | 256 |
262 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller | 257 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller |
263 // than kMaxToplevelSourceSize. | 258 // than kMaxToplevelSourceSize. |
264 // TODO(rmcilroy): Consider whether we should optimize small functions when | |
265 // they are first seen on the stack (e.g., kMaxSizeEarlyOpt). | |
266 | 259 |
267 if (function->IsMarkedForBaseline() || function->IsMarkedForOptimization() || | 260 if (function->IsMarkedForBaseline() || function->IsMarkedForOptimization() || |
268 function->IsMarkedForConcurrentOptimization() || | 261 function->IsMarkedForConcurrentOptimization() || |
269 function->IsOptimized()) { | 262 function->IsOptimized()) { |
270 // TODO(rmcilroy): Support OSR in these cases. | 263 // TODO(rmcilroy): Support OSR in these cases. |
271 return; | 264 return; |
272 } | 265 } |
273 | 266 |
274 if (shared->optimization_disabled() && | 267 if (shared->optimization_disabled() && |
275 shared->disable_optimization_reason() == kOptimizationDisabledForTest) { | 268 shared->disable_optimization_reason() == kOptimizationDisabledForTest) { |
276 // Don't baseline functions which have been marked by NeverOptimizeFunction | 269 // Don't baseline functions which have been marked by NeverOptimizeFunction |
277 // in a test. | 270 // in a test. |
278 return; | 271 return; |
279 } | 272 } |
280 | 273 |
281 if (ticks >= kProfilerTicksBeforeBaseline) { | 274 if (ticks >= kProfilerTicksBeforeBaseline) { |
282 Baseline(function, "hot enough for baseline"); | 275 Baseline(function, "hot enough for baseline"); |
283 } | 276 } |
284 } | 277 } |
285 | 278 |
| 279 void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function) { |
| 280 if (function->IsInOptimizationQueue()) return; |
| 281 |
| 282 SharedFunctionInfo* shared = function->shared(); |
| 283 int ticks = shared->profiler_ticks(); |
| 284 |
| 285 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller |
| 286 // than kMaxToplevelSourceSize. |
| 287 if (function->IsMarkedForBaseline() || function->IsMarkedForOptimization() || |
| 288 function->IsMarkedForConcurrentOptimization() || |
| 289 function->IsOptimized()) { |
| 290 // TODO(rmcilroy): Support OSR in these cases. |
| 291 return; |
| 292 } |
| 293 |
| 294 if (shared->optimization_disabled()) { |
| 295 if (shared->deopt_count() >= FLAG_max_opt_count) { |
| 296 // If optimization was disabled due to many deoptimizations, |
| 297 // then check if the function is hot and try to reenable optimization. |
| 298 if (ticks >= kProfilerTicksBeforeReenablingOptimization) { |
| 299 shared->set_profiler_ticks(0); |
| 300 shared->TryReenableOptimization(); |
| 301 } |
| 302 } |
| 303 return; |
| 304 } |
| 305 if (function->IsOptimized()) return; |
| 306 |
| 307 if (ticks >= kProfilerTicksBeforeOptimization) { |
| 308 int typeinfo, generic, total, type_percentage, generic_percentage; |
| 309 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, |
| 310 &generic_percentage); |
| 311 if (type_percentage >= FLAG_type_info_threshold && |
| 312 generic_percentage <= FLAG_generic_ic_threshold) { |
| 313 // If this particular function hasn't had any ICs patched for enough |
| 314 // ticks, optimize it now. |
| 315 Optimize(function, "hot and stable"); |
| 316 } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { |
| 317 Optimize(function, "not much type info but very hot"); |
| 318 } else { |
| 319 if (FLAG_trace_opt_verbose) { |
| 320 PrintF("[not yet optimizing "); |
| 321 function->PrintName(); |
| 322 PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total, |
| 323 type_percentage); |
| 324 } |
| 325 } |
| 326 } |
| 327 // TODO(rmcilroy): Consider whether we should optimize small functions when |
| 328 // they are first seen on the stack (e.g., kMaxSizeEarlyOpt). |
| 329 } |
| 330 |
286 void RuntimeProfiler::MarkCandidatesForOptimization() { | 331 void RuntimeProfiler::MarkCandidatesForOptimization() { |
287 HandleScope scope(isolate_); | 332 HandleScope scope(isolate_); |
288 | 333 |
289 if (!isolate_->use_crankshaft()) return; | 334 if (!isolate_->use_crankshaft()) return; |
290 | 335 |
291 DisallowHeapAllocation no_gc; | 336 DisallowHeapAllocation no_gc; |
292 | 337 |
293 // Run through the JavaScript frames and collect them. If we already | 338 // Run through the JavaScript frames and collect them. If we already |
294 // have a sample of the function, we mark it for optimizations | 339 // have a sample of the function, we mark it for optimizations |
295 // (eagerly or lazily). | 340 // (eagerly or lazily). |
296 int frame_count = 0; | 341 int frame_count = 0; |
297 int frame_count_limit = FLAG_frame_count; | 342 int frame_count_limit = FLAG_frame_count; |
298 for (JavaScriptFrameIterator it(isolate_); | 343 for (JavaScriptFrameIterator it(isolate_); |
299 frame_count++ < frame_count_limit && !it.done(); | 344 frame_count++ < frame_count_limit && !it.done(); |
300 it.Advance()) { | 345 it.Advance()) { |
301 JavaScriptFrame* frame = it.frame(); | 346 JavaScriptFrame* frame = it.frame(); |
302 JSFunction* function = frame->function(); | 347 JSFunction* function = frame->function(); |
303 | 348 |
304 List<JSFunction*> functions(4); | 349 List<JSFunction*> functions(4); |
305 frame->GetFunctions(&functions); | 350 frame->GetFunctions(&functions); |
306 for (int i = functions.length(); --i >= 0; ) { | 351 for (int i = functions.length(); --i >= 0; ) { |
307 SharedFunctionInfo* shared_function_info = functions[i]->shared(); | 352 SharedFunctionInfo* shared_function_info = functions[i]->shared(); |
308 int ticks = shared_function_info->profiler_ticks(); | 353 int ticks = shared_function_info->profiler_ticks(); |
309 if (ticks < Smi::kMaxValue) { | 354 if (ticks < Smi::kMaxValue) { |
310 shared_function_info->set_profiler_ticks(ticks + 1); | 355 shared_function_info->set_profiler_ticks(ticks + 1); |
311 } | 356 } |
312 } | 357 } |
313 | 358 |
| 359 Compiler::CompilationTier next_tier = |
| 360 Compiler::NextCompilationTier(function); |
314 if (frame->is_interpreted()) { | 361 if (frame->is_interpreted()) { |
315 DCHECK(!frame->is_optimized()); | 362 if (next_tier == Compiler::BASELINE) { |
316 MaybeOptimizeIgnition(function); | 363 DCHECK(!frame->is_optimized()); |
| 364 MaybeBaselineIgnition(function); |
| 365 } else { |
| 366 DCHECK_EQ(next_tier, Compiler::OPTIMIZED); |
| 367 MaybeOptimizeIgnition(function); |
| 368 } |
317 } else { | 369 } else { |
| 370 DCHECK_EQ(next_tier, Compiler::OPTIMIZED); |
318 MaybeOptimizeFullCodegen(function, frame_count, frame->is_optimized()); | 371 MaybeOptimizeFullCodegen(function, frame_count, frame->is_optimized()); |
319 } | 372 } |
320 } | 373 } |
321 any_ic_changed_ = false; | 374 any_ic_changed_ = false; |
322 } | 375 } |
323 | 376 |
324 | 377 |
325 } // namespace internal | 378 } // namespace internal |
326 } // namespace v8 | 379 } // namespace v8 |
OLD | NEW |