Chromium Code Reviews| 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/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 static const int kOSRCodeSizeAllowancePerTick = | 48 static const int kOSRCodeSizeAllowancePerTick = |
| 49 4 * FullCodeGenerator::kCodeSizeMultiplier; | 49 4 * FullCodeGenerator::kCodeSizeMultiplier; |
| 50 static const int kOSRCodeSizeAllowancePerTickIgnition = | 50 static const int kOSRCodeSizeAllowancePerTickIgnition = |
| 51 4 * interpreter::Interpreter::kCodeSizeMultiplier; | 51 4 * interpreter::Interpreter::kCodeSizeMultiplier; |
| 52 | 52 |
| 53 // Maximum size in bytes of generated code for a function to be optimized | 53 // Maximum size in bytes of generated code for a function to be optimized |
| 54 // the very first time it is seen on the stack. | 54 // the very first time it is seen on the stack. |
| 55 static const int kMaxSizeEarlyOpt = | 55 static const int kMaxSizeEarlyOpt = |
| 56 5 * FullCodeGenerator::kCodeSizeMultiplier; | 56 5 * FullCodeGenerator::kCodeSizeMultiplier; |
| 57 | 57 |
| 58 #define OPTIMIZATION_REASON_LIST(V) \ | |
| 59 V(DoNotOptimize, "do not optimize") \ | |
| 60 V(HotAndStable, "hot and stable") \ | |
| 61 V(HotEnoughForBaseline, "hot enough for baseline") \ | |
| 62 V(HotWithoutMuchTypeInfo, "not much type info but very hot") \ | |
| 63 V(SmallFunction, "small function") | |
| 64 | |
| 65 enum class OptimizationReason : uint8_t { | |
| 66 #define OPTIMIZATION_REASON_CONSTANTS(Constant, message) k##Constant, | |
| 67 OPTIMIZATION_REASON_LIST(OPTIMIZATION_REASON_CONSTANTS) | |
| 68 #undef OPTIMIZATION_REASON_CONSTANTS | |
| 69 }; | |
| 70 | |
| 71 char const* OptimizationReasonToString(OptimizationReason reason) { | |
| 72 static char const* reasons[] = { | |
| 73 #define OPTIMIZATION_REASON_TEXTS(Constant, message) message, | |
| 74 OPTIMIZATION_REASON_LIST(OPTIMIZATION_REASON_TEXTS) | |
| 75 #undef OPTIMIZATION_REASON_TEXTS | |
| 76 }; | |
| 77 size_t const index = static_cast<size_t>(reason); | |
| 78 DCHECK_LT(index, arraysize(reasons)); | |
| 79 return reasons[index]; | |
| 80 } | |
| 81 | |
| 82 std::ostream& operator<<(std::ostream& os, OptimizationReason reason) { | |
| 83 switch (reason) { | |
|
rmcilroy
2016/09/23 08:10:34
Just call OptimizationReasonToString rather than a
klaasb
2016/09/23 08:31:39
Done.
| |
| 84 #define OPTIMIZATION_REASON_NAMES(Constant, message) \ | |
| 85 case OptimizationReason::k##Constant: \ | |
| 86 return os << #Constant; | |
| 87 OPTIMIZATION_REASON_LIST(OPTIMIZATION_REASON_NAMES) | |
| 88 #undef OPTIMIZATION_REASON_NAMES | |
| 89 } | |
| 90 UNREACHABLE(); | |
| 91 return os; | |
| 92 } | |
| 58 | 93 |
| 59 RuntimeProfiler::RuntimeProfiler(Isolate* isolate) | 94 RuntimeProfiler::RuntimeProfiler(Isolate* isolate) |
| 60 : isolate_(isolate), | 95 : isolate_(isolate), |
| 61 any_ic_changed_(false) { | 96 any_ic_changed_(false) { |
| 62 } | 97 } |
| 63 | 98 |
| 64 static void GetICCounts(JSFunction* function, int* ic_with_type_info_count, | 99 static void GetICCounts(JSFunction* function, int* ic_with_type_info_count, |
| 65 int* ic_generic_count, int* ic_total_count, | 100 int* ic_generic_count, int* ic_total_count, |
| 66 int* type_info_percentage, int* generic_percentage) { | 101 int* type_info_percentage, int* generic_percentage) { |
| 67 *ic_total_count = 0; | 102 *ic_total_count = 0; |
| 68 *ic_generic_count = 0; | 103 *ic_generic_count = 0; |
| 69 *ic_with_type_info_count = 0; | 104 *ic_with_type_info_count = 0; |
| 70 if (function->code()->kind() == Code::FUNCTION) { | 105 if (function->code()->kind() == Code::FUNCTION) { |
| 71 Code* shared_code = function->shared()->code(); | 106 Code* shared_code = function->shared()->code(); |
| 72 Object* raw_info = shared_code->type_feedback_info(); | 107 Object* raw_info = shared_code->type_feedback_info(); |
| 73 if (raw_info->IsTypeFeedbackInfo()) { | 108 if (raw_info->IsTypeFeedbackInfo()) { |
| 74 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info); | 109 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info); |
| 75 *ic_with_type_info_count = info->ic_with_type_info_count(); | 110 *ic_with_type_info_count = info->ic_with_type_info_count(); |
| 76 *ic_generic_count = info->ic_generic_count(); | 111 *ic_generic_count = info->ic_generic_count(); |
| 77 *ic_total_count = info->ic_total_count(); | 112 *ic_total_count = info->ic_total_count(); |
| 78 } | 113 } |
| 79 } | 114 } |
| 80 | 115 |
| 81 // Harvest vector-ics as well | 116 // Harvest vector-ics as well |
| 82 TypeFeedbackVector* vector = function->feedback_vector(); | 117 TypeFeedbackVector* vector = function->feedback_vector(); |
| 83 int with = 0, gen = 0; | 118 int with = 0, gen = 0, interpreter_total = 0; |
|
rmcilroy
2016/09/23 08:10:34
nit - type_vector_ic_count
klaasb
2016/09/23 08:31:40
Done.
| |
| 84 const bool is_interpreted = | 119 const bool is_interpreted = |
| 85 function->shared()->code()->is_interpreter_trampoline_builtin(); | 120 function->shared()->code()->is_interpreter_trampoline_builtin(); |
| 86 | 121 |
| 87 vector->ComputeCounts(&with, &gen, is_interpreted); | 122 vector->ComputeCounts(&with, &gen, &interpreter_total, is_interpreted); |
| 123 if (is_interpreted) { | |
| 124 *ic_total_count = interpreter_total; | |
|
rmcilroy
2016/09/23 08:10:34
DCHECK ic_total_count is zero beforehand
klaasb
2016/09/23 08:31:40
Done.
| |
| 125 } | |
| 88 *ic_with_type_info_count += with; | 126 *ic_with_type_info_count += with; |
| 89 *ic_generic_count += gen; | 127 *ic_generic_count += gen; |
| 90 | 128 |
| 91 if (*ic_total_count > 0) { | 129 if (*ic_total_count > 0) { |
| 92 *type_info_percentage = 100 * *ic_with_type_info_count / *ic_total_count; | 130 *type_info_percentage = 100 * *ic_with_type_info_count / *ic_total_count; |
| 93 *generic_percentage = 100 * *ic_generic_count / *ic_total_count; | 131 *generic_percentage = 100 * *ic_generic_count / *ic_total_count; |
| 94 } else { | 132 } else { |
| 95 *type_info_percentage = 100; // Compared against lower bound. | 133 *type_info_percentage = 100; // Compared against lower bound. |
| 96 *generic_percentage = 0; // Compared against upper bound. | 134 *generic_percentage = 0; // Compared against upper bound. |
| 97 } | 135 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 109 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, | 147 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, |
| 110 &generic_percentage); | 148 &generic_percentage); |
| 111 PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total, | 149 PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total, |
| 112 type_percentage); | 150 type_percentage); |
| 113 PrintF(", generic ICs: %d/%d (%d%%)", generic, total, generic_percentage); | 151 PrintF(", generic ICs: %d/%d (%d%%)", generic, total, generic_percentage); |
| 114 } | 152 } |
| 115 PrintF("]\n"); | 153 PrintF("]\n"); |
| 116 } | 154 } |
| 117 } | 155 } |
| 118 | 156 |
| 119 void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) { | 157 void RuntimeProfiler::Optimize(JSFunction* function, |
| 120 TraceRecompile(function, reason, "optimized"); | 158 OptimizationReason reason) { |
| 159 DCHECK_NE(reason, OptimizationReason::kDoNotOptimize); | |
| 160 TraceRecompile(function, OptimizationReasonToString(reason), "optimized"); | |
| 121 function->AttemptConcurrentOptimization(); | 161 function->AttemptConcurrentOptimization(); |
| 122 } | 162 } |
| 123 | 163 |
| 124 void RuntimeProfiler::Baseline(JSFunction* function, const char* reason) { | 164 void RuntimeProfiler::Baseline(JSFunction* function, |
| 125 TraceRecompile(function, reason, "baseline"); | 165 OptimizationReason reason) { |
| 166 DCHECK_NE(reason, OptimizationReason::kDoNotOptimize); | |
| 167 TraceRecompile(function, OptimizationReasonToString(reason), "baseline"); | |
| 126 | 168 |
| 127 // TODO(4280): Fix this to check function is compiled for the interpreter | 169 // TODO(4280): Fix this to check function is compiled for the interpreter |
| 128 // once we have a standard way to check that. For now function will only | 170 // once we have a standard way to check that. For now function will only |
| 129 // have a bytecode array if compiled for the interpreter. | 171 // have a bytecode array if compiled for the interpreter. |
| 130 DCHECK(function->shared()->HasBytecodeArray()); | 172 DCHECK(function->shared()->HasBytecodeArray()); |
| 131 function->MarkForBaseline(); | 173 function->MarkForBaseline(); |
| 132 } | 174 } |
| 133 | 175 |
| 134 void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame, | 176 void RuntimeProfiler::AttemptOnStackReplacement(JavaScriptFrame* frame, |
| 135 int loop_nesting_levels) { | 177 int loop_nesting_levels) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 int ticks = shared_code->profiler_ticks(); | 276 int ticks = shared_code->profiler_ticks(); |
| 235 | 277 |
| 236 if (ticks >= kProfilerTicksBeforeOptimization) { | 278 if (ticks >= kProfilerTicksBeforeOptimization) { |
| 237 int typeinfo, generic, total, type_percentage, generic_percentage; | 279 int typeinfo, generic, total, type_percentage, generic_percentage; |
| 238 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, | 280 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, |
| 239 &generic_percentage); | 281 &generic_percentage); |
| 240 if (type_percentage >= FLAG_type_info_threshold && | 282 if (type_percentage >= FLAG_type_info_threshold && |
| 241 generic_percentage <= FLAG_generic_ic_threshold) { | 283 generic_percentage <= FLAG_generic_ic_threshold) { |
| 242 // If this particular function hasn't had any ICs patched for enough | 284 // If this particular function hasn't had any ICs patched for enough |
| 243 // ticks, optimize it now. | 285 // ticks, optimize it now. |
| 244 Optimize(function, "hot and stable"); | 286 Optimize(function, OptimizationReason::kHotAndStable); |
| 245 } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { | 287 } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { |
| 246 Optimize(function, "not much type info but very hot"); | 288 Optimize(function, OptimizationReason::kHotWithoutMuchTypeInfo); |
| 247 } else { | 289 } else { |
| 248 shared_code->set_profiler_ticks(ticks + 1); | 290 shared_code->set_profiler_ticks(ticks + 1); |
| 249 if (FLAG_trace_opt_verbose) { | 291 if (FLAG_trace_opt_verbose) { |
| 250 PrintF("[not yet optimizing "); | 292 PrintF("[not yet optimizing "); |
| 251 function->PrintName(); | 293 function->PrintName(); |
| 252 PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total, | 294 PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total, |
| 253 type_percentage); | 295 type_percentage); |
| 254 } | 296 } |
| 255 } | 297 } |
| 256 } else if (!any_ic_changed_ && | 298 } else if (!any_ic_changed_ && |
| 257 shared_code->instruction_size() < kMaxSizeEarlyOpt) { | 299 shared_code->instruction_size() < kMaxSizeEarlyOpt) { |
| 258 // If no IC was patched since the last tick and this function is very | 300 // If no IC was patched since the last tick and this function is very |
| 259 // small, optimistically optimize it now. | 301 // small, optimistically optimize it now. |
| 260 int typeinfo, generic, total, type_percentage, generic_percentage; | 302 int typeinfo, generic, total, type_percentage, generic_percentage; |
| 261 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, | 303 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, |
| 262 &generic_percentage); | 304 &generic_percentage); |
| 263 if (type_percentage >= FLAG_type_info_threshold && | 305 if (type_percentage >= FLAG_type_info_threshold && |
| 264 generic_percentage <= FLAG_generic_ic_threshold) { | 306 generic_percentage <= FLAG_generic_ic_threshold) { |
| 265 Optimize(function, "small function"); | 307 Optimize(function, OptimizationReason::kSmallFunction); |
| 266 } else { | 308 } else { |
| 267 shared_code->set_profiler_ticks(ticks + 1); | 309 shared_code->set_profiler_ticks(ticks + 1); |
| 268 } | 310 } |
| 269 } else { | 311 } else { |
| 270 shared_code->set_profiler_ticks(ticks + 1); | 312 shared_code->set_profiler_ticks(ticks + 1); |
| 271 } | 313 } |
| 272 } | 314 } |
| 273 | 315 |
| 274 void RuntimeProfiler::MaybeBaselineIgnition(JSFunction* function, | 316 void RuntimeProfiler::MaybeBaselineIgnition(JSFunction* function, |
| 275 JavaScriptFrame* frame) { | 317 JavaScriptFrame* frame) { |
| 276 if (function->IsInOptimizationQueue()) return; | 318 if (function->IsInOptimizationQueue()) return; |
| 277 | 319 |
| 320 if (MaybeOSRIgnition(function, frame)) return; | |
| 321 | |
| 278 SharedFunctionInfo* shared = function->shared(); | 322 SharedFunctionInfo* shared = function->shared(); |
| 279 int ticks = shared->profiler_ticks(); | 323 int ticks = shared->profiler_ticks(); |
| 280 | 324 |
| 281 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller | |
| 282 // than kMaxToplevelSourceSize. | |
| 283 | |
| 284 if (FLAG_always_osr) { | |
| 285 AttemptOnStackReplacement(frame, AbstractCode::kMaxLoopNestingMarker); | |
| 286 // Fall through and do a normal baseline compile as well. | |
| 287 } else if (!frame->is_optimized() && | |
| 288 (function->IsMarkedForBaseline() || | |
| 289 function->IsMarkedForOptimization() || | |
| 290 function->IsMarkedForConcurrentOptimization() || | |
| 291 function->IsOptimized())) { | |
| 292 // Attempt OSR if we are still running interpreted code even though the | |
| 293 // the function has long been marked or even already been optimized. | |
| 294 int64_t allowance = | |
| 295 kOSRCodeSizeAllowanceBaseIgnition + | |
| 296 static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition; | |
| 297 if (shared->bytecode_array()->Size() <= allowance) { | |
| 298 AttemptOnStackReplacement(frame); | |
| 299 } | |
| 300 return; | |
| 301 } | |
| 302 | |
| 303 if (shared->optimization_disabled() && | 325 if (shared->optimization_disabled() && |
| 304 shared->disable_optimization_reason() == kOptimizationDisabledForTest) { | 326 shared->disable_optimization_reason() == kOptimizationDisabledForTest) { |
| 305 // Don't baseline functions which have been marked by NeverOptimizeFunction | 327 // Don't baseline functions which have been marked by NeverOptimizeFunction |
| 306 // in a test. | 328 // in a test. |
| 307 return; | 329 return; |
| 308 } | 330 } |
| 309 | 331 |
| 310 if (ticks >= kProfilerTicksBeforeBaseline) { | 332 if (ticks >= kProfilerTicksBeforeBaseline) { |
| 311 Baseline(function, "hot enough for baseline"); | 333 Baseline(function, OptimizationReason::kHotEnoughForBaseline); |
| 312 } | 334 } |
| 313 } | 335 } |
| 314 | 336 |
| 315 void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function, | 337 void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function, |
| 316 JavaScriptFrame* frame) { | 338 JavaScriptFrame* frame) { |
| 317 if (function->IsInOptimizationQueue()) return; | 339 if (function->IsInOptimizationQueue()) return; |
| 318 | 340 |
| 341 if (MaybeOSRIgnition(function, frame)) return; | |
| 342 | |
| 319 SharedFunctionInfo* shared = function->shared(); | 343 SharedFunctionInfo* shared = function->shared(); |
| 320 int ticks = shared->profiler_ticks(); | 344 int ticks = shared->profiler_ticks(); |
| 321 | 345 |
| 346 if (shared->optimization_disabled()) { | |
| 347 if (shared->deopt_count() >= FLAG_max_opt_count) { | |
| 348 // If optimization was disabled due to many deoptimizations, | |
| 349 // then check if the function is hot and try to reenable optimization. | |
| 350 if (ticks >= kProfilerTicksBeforeReenablingOptimization) { | |
| 351 shared->set_profiler_ticks(0); | |
| 352 shared->TryReenableOptimization(); | |
| 353 } | |
| 354 } | |
| 355 return; | |
| 356 } | |
| 357 | |
| 358 if (function->IsOptimized()) return; | |
| 359 | |
| 360 auto reason = OptimizationHeuristicIgnition(function, frame); | |
|
rmcilroy
2016/09/23 08:10:34
Don't use auto unless it improves readability (htt
klaasb
2016/09/23 08:31:40
Done.
| |
| 361 | |
| 362 if (reason != OptimizationReason::kDoNotOptimize) { | |
| 363 Optimize(function, reason); | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 bool RuntimeProfiler::MaybeOSRIgnition(JSFunction* function, | |
| 368 JavaScriptFrame* frame) { | |
| 369 if (!FLAG_ignition_osr) return false; | |
| 370 | |
| 371 SharedFunctionInfo* shared = function->shared(); | |
| 372 int ticks = shared->profiler_ticks(); | |
| 373 | |
| 322 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller | 374 // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller |
| 323 // than kMaxToplevelSourceSize. | 375 // than kMaxToplevelSourceSize. |
| 324 | 376 |
| 325 if (FLAG_always_osr) { | 377 if (FLAG_always_osr) { |
| 326 AttemptOnStackReplacement(frame, AbstractCode::kMaxLoopNestingMarker); | 378 AttemptOnStackReplacement(frame, AbstractCode::kMaxLoopNestingMarker); |
| 327 // Fall through and do a normal optimized compile as well. | 379 // Do a normal baseline/optimized compile as well. |
| 380 return false; | |
|
rmcilroy
2016/09/23 08:10:34
Hmm, not keen on this. Could you just pull out the
klaasb
2016/09/23 08:31:40
Done.
| |
| 328 } else if (!frame->is_optimized() && | 381 } else if (!frame->is_optimized() && |
| 329 (function->IsMarkedForBaseline() || | 382 ((function->IsMarkedForBaseline() && |
| 383 OptimizationHeuristicIgnition(function, frame) != | |
| 384 OptimizationReason::kDoNotOptimize) || | |
|
rmcilroy
2016/09/23 08:10:34
Could you pull this out to a separate local for cl
klaasb
2016/09/23 08:31:40
Done.
| |
| 330 function->IsMarkedForOptimization() || | 385 function->IsMarkedForOptimization() || |
| 331 function->IsMarkedForConcurrentOptimization() || | 386 function->IsMarkedForConcurrentOptimization() || |
| 332 function->IsOptimized())) { | 387 function->IsOptimized())) { |
| 333 // Attempt OSR if we are still running interpreted code even though the | 388 // Attempt OSR if we are still running interpreted code even though the |
| 334 // the function has long been marked or even already been optimized. | 389 // the function has long been marked or even already been optimized. |
| 335 int64_t allowance = | 390 int64_t allowance = |
| 336 kOSRCodeSizeAllowanceBaseIgnition + | 391 kOSRCodeSizeAllowanceBaseIgnition + |
| 337 static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition; | 392 static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition; |
| 338 if (shared->bytecode_array()->Size() <= allowance) { | 393 if (shared->bytecode_array()->Size() <= allowance) { |
| 339 AttemptOnStackReplacement(frame); | 394 AttemptOnStackReplacement(frame); |
| 340 } | 395 } |
| 341 return; | 396 return true; |
| 342 } | 397 } |
| 398 return false; | |
| 399 } | |
| 343 | 400 |
| 344 if (shared->optimization_disabled()) { | 401 OptimizationReason RuntimeProfiler::OptimizationHeuristicIgnition( |
| 345 if (shared->deopt_count() >= FLAG_max_opt_count) { | 402 JSFunction* function, JavaScriptFrame* frame) { |
| 346 // If optimization was disabled due to many deoptimizations, | 403 SharedFunctionInfo* shared = function->shared(); |
| 347 // then check if the function is hot and try to reenable optimization. | 404 int ticks = shared->profiler_ticks(); |
| 348 if (ticks >= kProfilerTicksBeforeReenablingOptimization) { | |
| 349 shared->set_profiler_ticks(0); | |
| 350 shared->TryReenableOptimization(); | |
| 351 } | |
| 352 } | |
| 353 return; | |
| 354 } | |
| 355 if (function->IsOptimized()) return; | |
| 356 | 405 |
| 357 if (ticks >= kProfilerTicksBeforeOptimization) { | 406 if (ticks >= kProfilerTicksBeforeOptimization) { |
| 358 int typeinfo, generic, total, type_percentage, generic_percentage; | 407 int typeinfo, generic, total, type_percentage, generic_percentage; |
| 359 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, | 408 GetICCounts(function, &typeinfo, &generic, &total, &type_percentage, |
| 360 &generic_percentage); | 409 &generic_percentage); |
| 361 if (type_percentage >= FLAG_type_info_threshold && | 410 if (type_percentage >= FLAG_type_info_threshold && |
| 362 generic_percentage <= FLAG_generic_ic_threshold) { | 411 generic_percentage <= FLAG_generic_ic_threshold) { |
| 363 // If this particular function hasn't had any ICs patched for enough | 412 // If this particular function hasn't had any ICs patched for enough |
| 364 // ticks, optimize it now. | 413 // ticks, optimize it now. |
| 365 Optimize(function, "hot and stable"); | 414 return OptimizationReason::kHotAndStable; |
| 366 } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { | 415 } else if (ticks >= kTicksWhenNotEnoughTypeInfo) { |
| 367 Optimize(function, "not much type info but very hot"); | 416 return OptimizationReason::kHotWithoutMuchTypeInfo; |
| 368 } else { | 417 } else { |
| 369 if (FLAG_trace_opt_verbose) { | 418 if (FLAG_trace_opt_verbose) { |
| 370 PrintF("[not yet optimizing "); | 419 PrintF("[not yet optimizing "); |
| 371 function->PrintName(); | 420 function->PrintName(); |
| 372 PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total, | 421 PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total, |
| 373 type_percentage); | 422 type_percentage); |
| 374 } | 423 } |
| 424 return OptimizationReason::kDoNotOptimize; | |
| 375 } | 425 } |
| 376 } | 426 } |
| 377 // TODO(rmcilroy): Consider whether we should optimize small functions when | 427 // TODO(rmcilroy): Consider whether we should optimize small functions when |
| 378 // they are first seen on the stack (e.g., kMaxSizeEarlyOpt). | 428 // they are first seen on the stack (e.g., kMaxSizeEarlyOpt). |
| 429 return OptimizationReason::kDoNotOptimize; | |
| 379 } | 430 } |
| 380 | 431 |
| 381 void RuntimeProfiler::MarkCandidatesForOptimization() { | 432 void RuntimeProfiler::MarkCandidatesForOptimization() { |
| 382 HandleScope scope(isolate_); | 433 HandleScope scope(isolate_); |
| 383 | 434 |
| 384 if (!isolate_->use_crankshaft()) return; | 435 if (!isolate_->use_crankshaft()) return; |
| 385 | 436 |
| 386 DisallowHeapAllocation no_gc; | 437 DisallowHeapAllocation no_gc; |
| 387 | 438 |
| 388 // Run through the JavaScript frames and collect them. If we already | 439 // Run through the JavaScript frames and collect them. If we already |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 416 MaybeOptimizeIgnition(function, frame); | 467 MaybeOptimizeIgnition(function, frame); |
| 417 } | 468 } |
| 418 } else { | 469 } else { |
| 419 DCHECK_EQ(next_tier, Compiler::OPTIMIZED); | 470 DCHECK_EQ(next_tier, Compiler::OPTIMIZED); |
| 420 MaybeOptimizeFullCodegen(function, frame, frame_count); | 471 MaybeOptimizeFullCodegen(function, frame, frame_count); |
| 421 } | 472 } |
| 422 } | 473 } |
| 423 any_ic_changed_ = false; | 474 any_ic_changed_ = false; |
| 424 } | 475 } |
| 425 | 476 |
| 426 | |
| 427 } // namespace internal | 477 } // namespace internal |
| 428 } // namespace v8 | 478 } // namespace v8 |
| OLD | NEW |