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.

Reply via email to