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

Unified Diff: src/runtime-profiler.cc

Issue 2360913003: [interpreter] Compute and use type info percentage (Closed)
Patch Set: address comments Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime-profiler.h ('k') | src/type-feedback-vector.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/runtime-profiler.cc
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index df94ddfa2e687e139addb1bed79cbfe598777b77..b1e640c2ecb42c78215f6f632fb3a9b0aa13105b 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -55,6 +55,33 @@ static const int kOSRCodeSizeAllowancePerTickIgnition =
static const int kMaxSizeEarlyOpt =
5 * FullCodeGenerator::kCodeSizeMultiplier;
+#define OPTIMIZATION_REASON_LIST(V) \
+ V(DoNotOptimize, "do not optimize") \
+ V(HotAndStable, "hot and stable") \
+ V(HotEnoughForBaseline, "hot enough for baseline") \
+ V(HotWithoutMuchTypeInfo, "not much type info but very hot") \
+ V(SmallFunction, "small function")
+
+enum class OptimizationReason : uint8_t {
+#define OPTIMIZATION_REASON_CONSTANTS(Constant, message) k##Constant,
+ OPTIMIZATION_REASON_LIST(OPTIMIZATION_REASON_CONSTANTS)
+#undef OPTIMIZATION_REASON_CONSTANTS
+};
+
+char const* OptimizationReasonToString(OptimizationReason reason) {
+ static char const* reasons[] = {
+#define OPTIMIZATION_REASON_TEXTS(Constant, message) message,
+ OPTIMIZATION_REASON_LIST(OPTIMIZATION_REASON_TEXTS)
+#undef OPTIMIZATION_REASON_TEXTS
+ };
+ size_t const index = static_cast<size_t>(reason);
+ DCHECK_LT(index, arraysize(reasons));
+ return reasons[index];
+}
+
+std::ostream& operator<<(std::ostream& os, OptimizationReason reason) {
+ return os << OptimizationReasonToString(reason);
+}
RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
: isolate_(isolate),
@@ -80,11 +107,15 @@ static void GetICCounts(JSFunction* function, int* ic_with_type_info_count,
// Harvest vector-ics as well
TypeFeedbackVector* vector = function->feedback_vector();
- int with = 0, gen = 0;
+ int with = 0, gen = 0, type_vector_ic_count = 0;
const bool is_interpreted =
function->shared()->code()->is_interpreter_trampoline_builtin();
- vector->ComputeCounts(&with, &gen, is_interpreted);
+ vector->ComputeCounts(&with, &gen, &type_vector_ic_count, is_interpreted);
+ if (is_interpreted) {
+ DCHECK_EQ(*ic_total_count, 0);
+ *ic_total_count = type_vector_ic_count;
+ }
*ic_with_type_info_count += with;
*ic_generic_count += gen;
@@ -116,13 +147,17 @@ static void TraceRecompile(JSFunction* function, const char* reason,
}
}
-void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
- TraceRecompile(function, reason, "optimized");
+void RuntimeProfiler::Optimize(JSFunction* function,
+ OptimizationReason reason) {
+ DCHECK_NE(reason, OptimizationReason::kDoNotOptimize);
+ TraceRecompile(function, OptimizationReasonToString(reason), "optimized");
function->AttemptConcurrentOptimization();
}
-void RuntimeProfiler::Baseline(JSFunction* function, const char* reason) {
- TraceRecompile(function, reason, "baseline");
+void RuntimeProfiler::Baseline(JSFunction* function,
+ OptimizationReason reason) {
+ DCHECK_NE(reason, OptimizationReason::kDoNotOptimize);
+ TraceRecompile(function, OptimizationReasonToString(reason), "baseline");
// TODO(4280): Fix this to check function is compiled for the interpreter
// once we have a standard way to check that. For now function will only
@@ -241,9 +276,9 @@ void RuntimeProfiler::MaybeOptimizeFullCodegen(JSFunction* function,
generic_percentage <= FLAG_generic_ic_threshold) {
// If this particular function hasn't had any ICs patched for enough
// ticks, optimize it now.
- Optimize(function, "hot and stable");
+ Optimize(function, OptimizationReason::kHotAndStable);
} else if (ticks >= kTicksWhenNotEnoughTypeInfo) {
- Optimize(function, "not much type info but very hot");
+ Optimize(function, OptimizationReason::kHotWithoutMuchTypeInfo);
} else {
shared_code->set_profiler_ticks(ticks + 1);
if (FLAG_trace_opt_verbose) {
@@ -262,7 +297,7 @@ void RuntimeProfiler::MaybeOptimizeFullCodegen(JSFunction* function,
&generic_percentage);
if (type_percentage >= FLAG_type_info_threshold &&
generic_percentage <= FLAG_generic_ic_threshold) {
- Optimize(function, "small function");
+ Optimize(function, OptimizationReason::kSmallFunction);
} else {
shared_code->set_profiler_ticks(ticks + 1);
}
@@ -275,31 +310,16 @@ void RuntimeProfiler::MaybeBaselineIgnition(JSFunction* function,
JavaScriptFrame* frame) {
if (function->IsInOptimizationQueue()) return;
- SharedFunctionInfo* shared = function->shared();
- int ticks = shared->profiler_ticks();
-
- // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller
- // than kMaxToplevelSourceSize.
-
if (FLAG_always_osr) {
AttemptOnStackReplacement(frame, AbstractCode::kMaxLoopNestingMarker);
// Fall through and do a normal baseline compile as well.
- } else if (!frame->is_optimized() &&
- (function->IsMarkedForBaseline() ||
- function->IsMarkedForOptimization() ||
- function->IsMarkedForConcurrentOptimization() ||
- function->IsOptimized())) {
- // Attempt OSR if we are still running interpreted code even though the
- // the function has long been marked or even already been optimized.
- int64_t allowance =
- kOSRCodeSizeAllowanceBaseIgnition +
- static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition;
- if (shared->bytecode_array()->Size() <= allowance) {
- AttemptOnStackReplacement(frame);
- }
+ } else if (MaybeOSRIgnition(function, frame)) {
return;
}
+ SharedFunctionInfo* shared = function->shared();
+ int ticks = shared->profiler_ticks();
+
if (shared->optimization_disabled() &&
shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
// Don't baseline functions which have been marked by NeverOptimizeFunction
@@ -308,7 +328,7 @@ void RuntimeProfiler::MaybeBaselineIgnition(JSFunction* function,
}
if (ticks >= kProfilerTicksBeforeBaseline) {
- Baseline(function, "hot enough for baseline");
+ Baseline(function, OptimizationReason::kHotEnoughForBaseline);
}
}
@@ -316,31 +336,16 @@ void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
JavaScriptFrame* frame) {
if (function->IsInOptimizationQueue()) return;
- SharedFunctionInfo* shared = function->shared();
- int ticks = shared->profiler_ticks();
-
- // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller
- // than kMaxToplevelSourceSize.
-
if (FLAG_always_osr) {
AttemptOnStackReplacement(frame, AbstractCode::kMaxLoopNestingMarker);
// Fall through and do a normal optimized compile as well.
- } else if (!frame->is_optimized() &&
- (function->IsMarkedForBaseline() ||
- function->IsMarkedForOptimization() ||
- function->IsMarkedForConcurrentOptimization() ||
- function->IsOptimized())) {
- // Attempt OSR if we are still running interpreted code even though the
- // the function has long been marked or even already been optimized.
- int64_t allowance =
- kOSRCodeSizeAllowanceBaseIgnition +
- static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition;
- if (shared->bytecode_array()->Size() <= allowance) {
- AttemptOnStackReplacement(frame);
- }
+ } else if (MaybeOSRIgnition(function, frame)) {
return;
}
+ SharedFunctionInfo* shared = function->shared();
+ int ticks = shared->profiler_ticks();
+
if (shared->optimization_disabled()) {
if (shared->deopt_count() >= FLAG_max_opt_count) {
// If optimization was disabled due to many deoptimizations,
@@ -352,8 +357,51 @@ void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
}
return;
}
+
if (function->IsOptimized()) return;
+ OptimizationReason reason = ShouldOptimizeIgnition(function, frame);
+
+ if (reason != OptimizationReason::kDoNotOptimize) {
+ Optimize(function, reason);
+ }
+}
+
+bool RuntimeProfiler::MaybeOSRIgnition(JSFunction* function,
+ JavaScriptFrame* frame) {
+ if (!FLAG_ignition_osr) return false;
+
+ SharedFunctionInfo* shared = function->shared();
+ int ticks = shared->profiler_ticks();
+
+ // TODO(rmcilroy): Also ensure we only OSR top-level code if it is smaller
+ // than kMaxToplevelSourceSize.
+
+ bool osr_before_baselined = function->IsMarkedForBaseline() &&
+ ShouldOptimizeIgnition(function, frame) !=
+ OptimizationReason::kDoNotOptimize;
+ if (!frame->is_optimized() &&
+ (osr_before_baselined || function->IsMarkedForOptimization() ||
+ function->IsMarkedForConcurrentOptimization() ||
+ function->IsOptimized())) {
+ // Attempt OSR if we are still running interpreted code even though the
+ // the function has long been marked or even already been optimized.
+ int64_t allowance =
+ kOSRCodeSizeAllowanceBaseIgnition +
+ static_cast<int64_t>(ticks) * kOSRCodeSizeAllowancePerTickIgnition;
+ if (shared->bytecode_array()->Size() <= allowance) {
+ AttemptOnStackReplacement(frame);
+ }
+ return true;
+ }
+ return false;
+}
+
+OptimizationReason RuntimeProfiler::ShouldOptimizeIgnition(
+ JSFunction* function, JavaScriptFrame* frame) {
+ SharedFunctionInfo* shared = function->shared();
+ int ticks = shared->profiler_ticks();
+
if (ticks >= kProfilerTicksBeforeOptimization) {
int typeinfo, generic, total, type_percentage, generic_percentage;
GetICCounts(function, &typeinfo, &generic, &total, &type_percentage,
@@ -362,9 +410,9 @@ void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
generic_percentage <= FLAG_generic_ic_threshold) {
// If this particular function hasn't had any ICs patched for enough
// ticks, optimize it now.
- Optimize(function, "hot and stable");
+ return OptimizationReason::kHotAndStable;
} else if (ticks >= kTicksWhenNotEnoughTypeInfo) {
- Optimize(function, "not much type info but very hot");
+ return OptimizationReason::kHotWithoutMuchTypeInfo;
} else {
if (FLAG_trace_opt_verbose) {
PrintF("[not yet optimizing ");
@@ -372,10 +420,12 @@ void RuntimeProfiler::MaybeOptimizeIgnition(JSFunction* function,
PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo, total,
type_percentage);
}
+ return OptimizationReason::kDoNotOptimize;
}
}
// TODO(rmcilroy): Consider whether we should optimize small functions when
// they are first seen on the stack (e.g., kMaxSizeEarlyOpt).
+ return OptimizationReason::kDoNotOptimize;
}
void RuntimeProfiler::MarkCandidatesForOptimization() {
@@ -423,6 +473,5 @@ void RuntimeProfiler::MarkCandidatesForOptimization() {
any_ic_changed_ = false;
}
-
} // namespace internal
} // namespace v8
« no previous file with comments | « src/runtime-profiler.h ('k') | src/type-feedback-vector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698