Revision: 22887
Author: [email protected]
Date: Tue Aug 5 17:06:01 2014 UTC
Log: Track number of generic ICs per function
and use it to disable optimization if too many ICs are generic.
[email protected]
Review URL: https://codereview.chromium.org/441643008
http://code.google.com/p/v8/source/detail?r=22887
Modified:
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime-profiler.cc
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Mon Aug 4 18:17:54 2014
UTC
+++ /branches/bleeding_edge/src/flag-definitions.h Tue Aug 5 17:06:01 2014
UTC
@@ -352,6 +352,8 @@
"execution budget before interrupt is triggered")
DEFINE_INT(type_info_threshold, 25,
"percentage of ICs that must have type info to allow
optimization")
+DEFINE_INT(generic_ic_threshold, 30,
+ "max percentage of megamorphic/generic ICs to allow
optimization")
DEFINE_INT(self_opt_count, 130, "call count before self-optimization")
DEFINE_BOOL(trace_opt_verbose, false, "extra verbose compilation tracing")
=======================================
--- /branches/bleeding_edge/src/ic.cc Tue Aug 5 11:22:29 2014 UTC
+++ /branches/bleeding_edge/src/ic.cc Tue Aug 5 17:06:01 2014 UTC
@@ -334,13 +334,39 @@
}
-static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State
new_state) {
- bool was_uninitialized =
- old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
- bool is_uninitialized =
- new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
- return (was_uninitialized && !is_uninitialized) ? 1 :
- (!was_uninitialized && is_uninitialized) ? -1 : 0;
+static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State
new_state,
+ int* polymorphic_delta,
+ int* generic_delta) {
+ switch (old_state) {
+ case UNINITIALIZED:
+ case PREMONOMORPHIC:
+ if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
+ if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
+ *polymorphic_delta = 1;
+ } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
+ *generic_delta = 1;
+ }
+ break;
+ case MONOMORPHIC:
+ case POLYMORPHIC:
+ if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
+ *polymorphic_delta = -1;
+ if (new_state == MEGAMORPHIC || new_state == GENERIC) {
+ *generic_delta = 1;
+ }
+ break;
+ case MEGAMORPHIC:
+ case GENERIC:
+ if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
+ *generic_delta = -1;
+ if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
+ *polymorphic_delta = 1;
+ }
+ break;
+ case PROTOTYPE_FAILURE:
+ case DEBUG_STUB:
+ UNREACHABLE();
+ }
}
@@ -350,21 +376,20 @@
inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
if (host->kind() != Code::FUNCTION) return;
- if (FLAG_type_info_threshold > 0 &&
- old_target->is_inline_cache_stub() &&
- target->is_inline_cache_stub()) {
- int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
- target->ic_state());
- // Call ICs don't have interesting state changes from this point
- // of view.
- DCHECK(target->kind() != Code::CALL_IC || delta == 0);
-
- // Not all Code objects have TypeFeedbackInfo.
- if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
- TypeFeedbackInfo* info =
- TypeFeedbackInfo::cast(host->type_feedback_info());
- info->change_ic_with_type_info_count(delta);
- }
+ if (FLAG_type_info_threshold > 0 && old_target->is_inline_cache_stub() &&
+ target->is_inline_cache_stub() &&
+ // Call ICs don't have interesting state changes from this point
+ // of view.
+ target->kind() != Code::CALL_IC &&
+ // Not all Code objects have TypeFeedbackInfo.
+ host->type_feedback_info()->IsTypeFeedbackInfo()) {
+ int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
+ int generic_delta = 0; // "Generic" here includes megamorphic.
+ ComputeTypeInfoCountDelta(old_target->ic_state(), target->ic_state(),
+ &polymorphic_delta, &generic_delta);
+ TypeFeedbackInfo* info =
TypeFeedbackInfo::cast(host->type_feedback_info());
+ info->change_ic_with_type_info_count(polymorphic_delta);
+ info->change_ic_generic_count(generic_delta);
}
if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
TypeFeedbackInfo* info =
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Mon Aug 4 11:34:54 2014
UTC
+++ /branches/bleeding_edge/src/objects-debug.cc Tue Aug 5 17:06:01 2014
UTC
@@ -349,6 +349,7 @@
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
VerifyObjectField(kStorage1Offset);
VerifyObjectField(kStorage2Offset);
+ VerifyObjectField(kStorage3Offset);
}
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Tue Aug 5 08:18:22 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Tue Aug 5 17:06:01 2014 UTC
@@ -7071,6 +7071,7 @@
void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
+ if (delta == 0) return;
int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
// We can get negative count here when the type-feedback info is
@@ -7084,11 +7085,27 @@
WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
}
}
+
+
+int TypeFeedbackInfo::ic_generic_count() {
+ return Smi::cast(READ_FIELD(this, kStorage3Offset))->value();
+}
+
+
+void TypeFeedbackInfo::change_ic_generic_count(int delta) {
+ if (delta == 0) return;
+ int new_count = ic_generic_count() + delta;
+ if (new_count >= 0) {
+ new_count &= ~Smi::kMinValue;
+ WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count));
+ }
+}
void TypeFeedbackInfo::initialize_storage() {
WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
+ WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(0));
}
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Wed Jul 30 13:54:45 2014
UTC
+++ /branches/bleeding_edge/src/objects-printer.cc Tue Aug 5 17:06:01 2014
UTC
@@ -486,7 +486,8 @@
void TypeFeedbackInfo::TypeFeedbackInfoPrint(OStream& os) { // NOLINT
HeapObject::PrintHeader(os, "TypeFeedbackInfo");
os << " - ic_total_count: " << ic_total_count()
- << ", ic_with_type_info_count: " << ic_with_type_info_count() << "\n";
+ << ", ic_with_type_info_count: " << ic_with_type_info_count()
+ << ", ic_generic_count: " << ic_generic_count() << "\n";
}
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Aug 5 14:19:22 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Tue Aug 5 17:06:01 2014 UTC
@@ -8507,7 +8507,10 @@
inline void set_ic_total_count(int count);
inline int ic_with_type_info_count();
- inline void change_ic_with_type_info_count(int count);
+ inline void change_ic_with_type_info_count(int delta);
+
+ inline int ic_generic_count();
+ inline void change_ic_generic_count(int delta);
inline void initialize_storage();
@@ -8526,7 +8529,8 @@
static const int kStorage1Offset = HeapObject::kHeaderSize;
static const int kStorage2Offset = kStorage1Offset + kPointerSize;
- static const int kSize = kStorage2Offset + kPointerSize;
+ static const int kStorage3Offset = kStorage2Offset + kPointerSize;
+ static const int kSize = kStorage3Offset + kPointerSize;
// TODO(mvstanton): move these sentinel declarations to shared function
info.
// The object that indicates an uninitialized cache.
=======================================
--- /branches/bleeding_edge/src/runtime-profiler.cc Tue Aug 5 08:18:22
2014 UTC
+++ /branches/bleeding_edge/src/runtime-profiler.cc Tue Aug 5 17:06:01
2014 UTC
@@ -57,21 +57,26 @@
}
-static void GetICCounts(Code* shared_code,
- int* ic_with_type_info_count,
- int* ic_total_count,
- int* percentage) {
+static void GetICCounts(Code* shared_code, int* ic_with_type_info_count,
+ int* ic_generic_count, int* ic_total_count,
+ int* type_info_percentage, int*
generic_percentage) {
*ic_total_count = 0;
+ *ic_generic_count = 0;
*ic_with_type_info_count = 0;
Object* raw_info = shared_code->type_feedback_info();
if (raw_info->IsTypeFeedbackInfo()) {
TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info);
*ic_with_type_info_count = info->ic_with_type_info_count();
+ *ic_generic_count = info->ic_generic_count();
*ic_total_count = info->ic_total_count();
}
- *percentage = *ic_total_count > 0
- ? 100 * *ic_with_type_info_count / *ic_total_count
- : 100;
+ if (*ic_total_count > 0) {
+ *type_info_percentage = 100 * *ic_with_type_info_count /
*ic_total_count;
+ *generic_percentage = 100 * *ic_generic_count / *ic_total_count;
+ } else {
+ *type_info_percentage = 100; // Compared against lower bound.
+ *generic_percentage = 0; // Compared against upper bound.
+ }
}
@@ -83,9 +88,12 @@
function->ShortPrint();
PrintF(" for recompilation, reason: %s", reason);
if (FLAG_type_info_threshold > 0) {
- int typeinfo, total, percentage;
- GetICCounts(function->shared()->code(), &typeinfo, &total,
&percentage);
- PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total,
percentage);
+ int typeinfo, generic, total, type_percentage, generic_percentage;
+ GetICCounts(function->shared()->code(), &typeinfo, &generic, &total,
+ &type_percentage, &generic_percentage);
+ PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total,
+ type_percentage);
+ PrintF(", generic ICs: %d/%d (%d%%)", generic, total,
generic_percentage);
}
PrintF("]\n");
}
@@ -227,9 +235,11 @@
int ticks = shared_code->profiler_ticks();
if (ticks >= kProfilerTicksBeforeOptimization) {
- int typeinfo, total, percentage;
- GetICCounts(shared_code, &typeinfo, &total, &percentage);
- if (percentage >= FLAG_type_info_threshold) {
+ int typeinfo, generic, total, type_percentage, generic_percentage;
+ GetICCounts(shared_code, &typeinfo, &generic, &total,
&type_percentage,
+ &generic_percentage);
+ if (type_percentage >= FLAG_type_info_threshold &&
+ 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");
@@ -240,15 +250,23 @@
if (FLAG_trace_opt_verbose) {
PrintF("[not yet optimizing ");
function->PrintName();
- PrintF(", not enough type info: %d/%d (%d%%)]\n",
- typeinfo, total, percentage);
+ PrintF(", not enough type info: %d/%d (%d%%)]\n", typeinfo,
total,
+ type_percentage);
}
}
} else if (!any_ic_changed_ &&
shared_code->instruction_size() < kMaxSizeEarlyOpt) {
// If no IC was patched since the last tick and this function is very
// small, optimistically optimize it now.
- Optimize(function, "small function");
+ int typeinfo, generic, total, type_percentage, generic_percentage;
+ GetICCounts(shared_code, &typeinfo, &generic, &total,
&type_percentage,
+ &generic_percentage);
+ if (type_percentage >= FLAG_type_info_threshold &&
+ generic_percentage <= FLAG_generic_ic_threshold) {
+ Optimize(function, "small function");
+ } else {
+ shared_code->set_profiler_ticks(ticks + 1);
+ }
} else {
shared_code->set_profiler_ticks(ticks + 1);
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.