Merge UpdateStoreCaches into a single function dispatching on ComputeStoreMonorphic...
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 25 Jan 2013 10:34:17 +0000 (10:34 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 25 Jan 2013 10:34:17 +0000 (10:34 +0000)
Review URL: https://chromiumcodereview.appspot.com/12057003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13503 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ic.cc
src/ic.h

index 65d3f65..30117c9 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -963,39 +963,20 @@ MaybeObject* LoadIC::Load(State state,
 }
 
 
-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 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
           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 @@ MaybeObject* StoreIC::Store(State state,
   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 @@ MaybeObject* StoreIC::Store(State state,
 }
 
 
-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 @@ void StoreIC::UpdateStoreCaches(LookupResult* lookup,
   // 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 @@ void StoreIC::UpdateStoreCaches(LookupResult* lookup,
         // 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 @@ void StoreIC::UpdateStoreCaches(LookupResult* lookup,
       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 @@ MaybeObject* KeyedStoreIC::Store(State state,
 }
 
 
-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 @@ void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup,
 
       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 @@ void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup,
     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();
 }
 
 
index 3ffe4e0..ea452a3 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -165,6 +165,21 @@ class IC {
   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.
   Address fp_;
@@ -361,7 +376,6 @@ class LoadIC: public IC {
   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 @@ class StoreIC: public IC {
 
   // 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 @@ class KeyedStoreIC: public StoreIC {
  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();