Revision: 13503
Author:   [email protected]
Date:     Fri Jan 25 02:34:17 2013
Log: Merge UpdateStoreCaches into a single function dispatching on ComputeStoreMonorphic and UpdateMegamorphicCache.

Review URL: https://chromiumcodereview.appspot.com/12057003
http://code.google.com/p/v8/source/detail?r=13503

Modified:
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/ic.h

=======================================
--- /branches/bleeding_edge/src/ic.cc   Thu Jan 24 05:02:45 2013
+++ /branches/bleeding_edge/src/ic.cc   Fri Jan 25 02:34:17 2013
@@ -963,39 +963,20 @@
 }


-void LoadIC::UpdateCaches(LookupResult* lookup,
-                          State state,
-                          Handle<Object> object,
-                          Handle<String> name) {
-  // Bail out if the result is not cacheable.
-  if (!lookup->IsCacheable()) return;
-
-  // Loading properties from values is not common, so don't try to
-  // deal with non-JS objects here.
-  if (!object->IsJSObject()) return;
-
-  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
-
-  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-  Handle<Code> code;
-  if (state == UNINITIALIZED) {
-    // This is the first time we execute this inline cache.
-    // Set the target to the pre monomorphic stub to delay
-    // setting the monomorphic state.
-    code = pre_monomorphic_stub();
-  } else {
-    code = ComputeLoadMonomorphic(lookup, receiver, name);
-    if (code.is_null()) return;
-  }
-
-  // Patch the call site depending on the state of the cache.
+void IC::PatchCache(State state,
+                    StrictModeFlag strict_mode,
+                    Handle<JSObject> receiver,
+                    Handle<String> name,
+                    Handle<Code> code) {
   switch (state) {
     case UNINITIALIZED:
     case PREMONOMORPHIC:
     case MONOMORPHIC_PROTOTYPE_FAILURE:
+    case POLYMORPHIC:
       set_target(*code);
       break;
     case MONOMORPHIC:
+      // Only move to megamorphic if the target changes.
       if (target() != *code) {
         // We are transitioning from monomorphic to megamorphic case.
         // Place the current monomorphic stub and stub compiled for
@@ -1005,25 +986,53 @@
           UpdateMegamorphicCache(map, *name, target());
         }
         UpdateMegamorphicCache(receiver->map(), *name, *code);
-        set_target(*megamorphic_stub());
+        set_target((strict_mode == kStrictMode)
+                     ? *megamorphic_stub_strict()
+                     : *megamorphic_stub());
       }
       break;
     case MEGAMORPHIC:
+      // Update the stub cache.
       UpdateMegamorphicCache(receiver->map(), *name, *code);
       break;
-    case DEBUG_STUB:
-      break;
-    case POLYMORPHIC:
     case GENERIC:
-      UNREACHABLE();
+    case DEBUG_STUB:
       break;
   }
+}
+
+
+void LoadIC::UpdateCaches(LookupResult* lookup,
+                          State state,
+                          Handle<Object> object,
+                          Handle<String> name) {
+  // Bail out if the result is not cacheable.
+  if (!lookup->IsCacheable()) return;
+
+  // Loading properties from values is not common, so don't try to
+  // deal with non-JS objects here.
+  if (!object->IsJSObject()) return;
+
+  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;

+  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+  Handle<Code> code;
+  if (state == UNINITIALIZED) {
+    // This is the first time we execute this inline cache.
+    // Set the target to the pre monomorphic stub to delay
+    // setting the monomorphic state.
+    code = pre_monomorphic_stub();
+  } else {
+    code = ComputeLoadMonomorphic(lookup, receiver, name);
+    if (code.is_null()) return;
+  }
+
+  PatchCache(state, kNonStrictMode, receiver, name, code);
   TRACE_IC("LoadIC", name, state, target());
 }


-void LoadIC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
+void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
   // Cache code holding map should be consistent with
   // GenerateMonomorphicCacheProbe.
   isolate()->stub_cache()->Set(name, map, code);
@@ -1424,7 +1433,7 @@
   LookupResult lookup(isolate());
   if (LookupForWrite(receiver, name, &lookup)) {
     if (FLAG_use_ic) {
- UpdateStoreCaches(&lookup, state, strict_mode, receiver, name, value);
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
     }
   } else if (strict_mode == kStrictMode &&
              !(lookup.IsProperty() && lookup.IsReadOnly()) &&
@@ -1438,12 +1447,12 @@
 }


-void StoreIC::UpdateStoreCaches(LookupResult* lookup,
-                                State state,
-                                StrictModeFlag strict_mode,
-                                Handle<JSObject> receiver,
-                                Handle<String> name,
-                                Handle<Object> value) {
+void StoreIC::UpdateCaches(LookupResult* lookup,
+                           State state,
+                           StrictModeFlag strict_mode,
+                           Handle<JSObject> receiver,
+                           Handle<String> name,
+                           Handle<Object> value) {
   ASSERT(!receiver->IsJSGlobalProxy());
   ASSERT(StoreICableLookup(lookup));
   ASSERT(lookup->IsFound());
@@ -1451,22 +1460,25 @@
   // These are not cacheable, so we never see such LookupResults here.
   ASSERT(!lookup->IsHandler());

-  // If the property has a non-field type allowing map transitions
-  // where there is extra room in the object, we leave the IC in its
-  // current state.
-  PropertyType type = lookup->type();
+  Handle<Code> code =
+      ComputeStoreMonomorphic(lookup, strict_mode, receiver, name);
+  if (code.is_null()) return;

-  // Compute the code stub for this store; used for rewriting to
-  // monomorphic state and making sure that the code stub is in the
-  // stub cache.
+  PatchCache(state, strict_mode, receiver, name, code);
+  TRACE_IC("StoreIC", name, state, target());
+}
+
+
+Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
+                                              StrictModeFlag strict_mode,
+                                              Handle<JSObject> receiver,
+                                              Handle<String> name) {
   Handle<JSObject> holder(lookup->holder());
-  Handle<Code> code;
-  switch (type) {
+  switch (lookup->type()) {
     case FIELD:
-      code = isolate()->stub_cache()->ComputeStoreField(
+      return isolate()->stub_cache()->ComputeStoreField(
           name, receiver, lookup->GetFieldIndex().field_index(),
           Handle<Map>::null(), strict_mode);
-      break;
     case NORMAL:
       if (receiver->IsGlobalObject()) {
// The stub generated for the global object picks the value directly
@@ -1474,44 +1486,39 @@
         // global object.
         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
         Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
-        code = isolate()->stub_cache()->ComputeStoreGlobal(
+        return isolate()->stub_cache()->ComputeStoreGlobal(
             name, global, cell, strict_mode);
-      } else {
-        if (!holder.is_identical_to(receiver)) return;
-        code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
       }
-      break;
+      if (!holder.is_identical_to(receiver)) break;
+      return isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
     case CALLBACKS: {
       Handle<Object> callback(lookup->GetCallbackObject());
       if (callback->IsAccessorInfo()) {
         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
-        if (v8::ToCData<Address>(info->setter()) == 0) return;
-        if (!holder->HasFastProperties()) return;
-        if (!info->IsCompatibleReceiver(*receiver)) return;
-        code = isolate()->stub_cache()->ComputeStoreCallback(
+        if (v8::ToCData<Address>(info->setter()) == 0) break;
+        if (!holder->HasFastProperties()) break;
+        if (!info->IsCompatibleReceiver(*receiver)) break;
+        return isolate()->stub_cache()->ComputeStoreCallback(
             name, receiver, holder, info, strict_mode);
       } else if (callback->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
-        if (!setter->IsJSFunction()) return;
-        if (holder->IsGlobalObject()) return;
-        if (!holder->HasFastProperties()) return;
-        code = isolate()->stub_cache()->ComputeStoreViaSetter(
+        if (!setter->IsJSFunction()) break;
+        if (holder->IsGlobalObject()) break;
+        if (!holder->HasFastProperties()) break;
+        return isolate()->stub_cache()->ComputeStoreViaSetter(
             name, receiver, holder, Handle<JSFunction>::cast(setter),
             strict_mode);
-      } else {
-        ASSERT(callback->IsForeign());
-        // No IC support for old-style native accessors.
-        return;
       }
+      ASSERT(callback->IsForeign());
+      // No IC support for old-style native accessors.
       break;
     }
     case INTERCEPTOR:
       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
-      code = isolate()->stub_cache()->ComputeStoreInterceptor(
+      return isolate()->stub_cache()->ComputeStoreInterceptor(
           name, receiver, strict_mode);
-      break;
     case CONSTANT_FUNCTION:
-      return;
+      break;
     case TRANSITION: {
       Handle<Map> transition(lookup->GetTransitionTarget());
       int descriptor = transition->LastAdded();
@@ -1519,56 +1526,18 @@
DescriptorArray* target_descriptors = transition->instance_descriptors();
       PropertyDetails details = target_descriptors->GetDetails(descriptor);

-      if (details.type() != FIELD || details.attributes() != NONE) return;
+      if (details.type() != FIELD || details.attributes() != NONE) break;

       int field_index = target_descriptors->GetFieldIndex(descriptor);
-      code = isolate()->stub_cache()->ComputeStoreField(
+      return isolate()->stub_cache()->ComputeStoreField(
           name, receiver, field_index, transition, strict_mode);
-
-      break;
     }
     case NONEXISTENT:
     case HANDLER:
       UNREACHABLE();
-      return;
-  }
-
-  // Patch the call site depending on the state of the cache.
-  switch (state) {
-    case UNINITIALIZED:
-    case PREMONOMORPHIC:
-    case MONOMORPHIC_PROTOTYPE_FAILURE:
-      set_target(*code);
       break;
-    case MONOMORPHIC:
-      // Only move to megamorphic if the target changes.
-      if (target() != *code) {
-        // We are transitioning from monomorphic to megamorphic case.
-        // Place the current monomorphic stub and stub compiled for
-        // the receiver into stub cache.
-        Map* map = target()->FindFirstMap();
-        if (map != NULL) {
-          isolate()->stub_cache()->Set(*name, map, target());
-        }
-        isolate()->stub_cache()->Set(*name, receiver->map(), *code);
-        set_target((strict_mode == kStrictMode)
-                     ? *megamorphic_stub_strict()
-                     : *megamorphic_stub());
-      }
-      break;
-    case MEGAMORPHIC:
-      // Update the stub cache.
-      isolate()->stub_cache()->Set(*name, receiver->map(), *code);
-      break;
-    case DEBUG_STUB:
-      break;
-    case POLYMORPHIC:
-    case GENERIC:
-      UNREACHABLE();
-      break;
   }
-
-  TRACE_IC("StoreIC", name, state, target());
+  return Handle<Code>::null();
 }


@@ -1804,35 +1773,18 @@
 }


-void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup,
-                                     State state,
-                                     StrictModeFlag strict_mode,
-                                     Handle<JSObject> receiver,
-                                     Handle<String> name,
-                                     Handle<Object> value) {
-  ASSERT(!receiver->IsJSGlobalProxy());
-  ASSERT(StoreICableLookup(lookup));
-  ASSERT(lookup->IsFound());
-
-  // These are not cacheable, so we never see such LookupResults here.
-  ASSERT(!lookup->IsHandler());
-
+Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
+ StrictModeFlag strict_mode, + Handle<JSObject> receiver,
+                                                   Handle<String> name) {
   // If the property has a non-field type allowing map transitions
   // where there is extra room in the object, we leave the IC in its
   // current state.
-  PropertyType type = lookup->type();
-
-  // Compute the code stub for this store; used for rewriting to
-  // monomorphic state and making sure that the code stub is in the
-  // stub cache.
-  Handle<Code> code;
-
-  switch (type) {
+  switch (lookup->type()) {
     case FIELD:
-      code = isolate()->stub_cache()->ComputeKeyedStoreField(
+      return isolate()->stub_cache()->ComputeKeyedStoreField(
           name, receiver, lookup->GetFieldIndex().field_index(),
           Handle<Map>::null(), strict_mode);
-      break;
     case TRANSITION: {
       Handle<Map> transition(lookup->GetTransitionTarget());
       int descriptor = transition->LastAdded();
@@ -1842,9 +1794,8 @@

       if (details.type() == FIELD && details.attributes() == NONE) {
         int field_index = target_descriptors->GetFieldIndex(descriptor);
-        code = isolate()->stub_cache()->ComputeKeyedStoreField(
+        return isolate()->stub_cache()->ComputeKeyedStoreField(
             name, receiver, field_index, transition, strict_mode);
-        break;
       }
       // fall through.
     }
@@ -1854,43 +1805,15 @@
     case INTERCEPTOR:
       // Always rewrite to the generic case so that we do not
       // repeatedly try to rewrite.
-      code = (strict_mode == kStrictMode)
+      return (strict_mode == kStrictMode)
           ? generic_stub_strict()
           : generic_stub();
-      break;
     case HANDLER:
     case NONEXISTENT:
       UNREACHABLE();
-      return;
-  }
-
-  ASSERT(!code.is_null());
-
-  // Patch the call site depending on the state of the cache.
-  switch (state) {
-    case UNINITIALIZED:
-    case PREMONOMORPHIC:
-    case POLYMORPHIC:
-      set_target(*code);
       break;
-    case MONOMORPHIC:
-      // Only move to megamorphic if the target changes.
-      if (target() != *code) {
-        set_target((strict_mode == kStrictMode)
-                     ? *megamorphic_stub_strict()
-                     : *megamorphic_stub());
-      }
-      break;
-    case MEGAMORPHIC:
-    case GENERIC:
-    case DEBUG_STUB:
-      break;
-    case MONOMORPHIC_PROTOTYPE_FAILURE:
-      UNREACHABLE();
-      break;
   }
-
-  TRACE_IC("KeyedStoreIC", name, state, target());
+  return Handle<Code>::null();
 }


=======================================
--- /branches/bleeding_edge/src/ic.h    Thu Jan 24 05:02:45 2013
+++ /branches/bleeding_edge/src/ic.h    Fri Jan 25 02:34:17 2013
@@ -164,6 +164,21 @@
   static inline Code* GetTargetAtAddress(Address address);
   static inline void SetTargetAtAddress(Address address, Code* target);
static void PostPatching(Address address, Code* target, Code* old_target);
+
+  void PatchCache(State state,
+                  StrictModeFlag strict_mode,
+                  Handle<JSObject> receiver,
+                  Handle<String> name,
+                  Handle<Code> code);
+  virtual void UpdateMegamorphicCache(Map* map, String* name, Code* code);
+  virtual Handle<Code> megamorphic_stub() {
+    UNREACHABLE();
+    return Handle<Code>::null();
+  }
+  virtual Handle<Code> megamorphic_stub_strict() {
+    UNREACHABLE();
+    return Handle<Code>::null();
+  }

  private:
   // Frame pointer for the frame that uses (calls) the IC.
@@ -361,7 +376,6 @@
   virtual Handle<Code> ComputeLoadMonomorphic(LookupResult* lookup,
                                               Handle<JSObject> receiver,
                                               Handle<String> name);
-  virtual void UpdateMegamorphicCache(Map* map, String* name, Code* code);

  private:
   // Stub accessors.
@@ -502,12 +516,19 @@

   // Update the inline cache and the global stub cache based on the
   // lookup result.
-  virtual void UpdateStoreCaches(LookupResult* lookup,
-                                 State state,
-                                 StrictModeFlag strict_mode,
-                                 Handle<JSObject> receiver,
-                                 Handle<String> name,
-                                 Handle<Object> value);
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    StrictModeFlag strict_mode,
+                    Handle<JSObject> receiver,
+                    Handle<String> name,
+                    Handle<Object> value);
+  // Compute the code stub for this store; used for rewriting to
+  // monomorphic state and making sure that the code stub is in the
+  // stub cache.
+  virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
+                                               StrictModeFlag strict_mode,
+                                               Handle<JSObject> receiver,
+                                               Handle<String> name);

  private:
   void set_target(Code* code) {
@@ -607,13 +628,11 @@
  protected:
   virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }

-  // Update the inline cache.
-  virtual void UpdateStoreCaches(LookupResult* lookup,
-                                 State state,
-                                 StrictModeFlag strict_mode,
-                                 Handle<JSObject> receiver,
-                                 Handle<String> name,
-                                 Handle<Object> value);
+  virtual Handle<Code> ComputeStoreMonomorphic(LookupResult* lookup,
+                                               StrictModeFlag strict_mode,
+                                               Handle<JSObject> receiver,
+                                               Handle<String> name);
+ virtual void UpdateMegamorphicCache(Map* map, String* name, Code* code) { }

   virtual Handle<Code> megamorphic_stub() {
     return isolate()->builtins()->KeyedStoreIC_Generic();

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev


Reply via email to