Merge UpdateLoadCaches into a single function dispatching on
authorverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Jan 2013 13:02:45 +0000 (13:02 +0000)
committerverwaest@chromium.org <verwaest@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Jan 2013 13:02:45 +0000 (13:02 +0000)
ComputeLoadMonorphic and UpdateMegamorphicCache.

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

src/ic.cc
src/ic.h

index 49b3377..65d3f65 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -941,7 +941,7 @@ MaybeObject* LoadIC::Load(State state,
 
   // Update inline cache and stub cache.
   if (FLAG_use_ic) {
-    UpdateLoadCaches(&lookup, state, object, name);
+    UpdateCaches(&lookup, state, object, name);
   }
 
   PropertyAttributes attr;
@@ -963,89 +963,29 @@ MaybeObject* LoadIC::Load(State state,
 }
 
 
-void LoadIC::UpdateLoadCaches(LookupResult* lookup,
-                              State state,
-                              Handle<Object> object,
-                              Handle<String> name) {
+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;
-  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
 
   if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
 
-  // Compute the code stub for this load.
+  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 if (!lookup->IsProperty()) {
-    // Nonexistent property. The result is undefined.
-    code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
   } else {
-    // Compute monomorphic stub.
-    Handle<JSObject> holder(lookup->holder());
-    switch (lookup->type()) {
-      case FIELD:
-        code = isolate()->stub_cache()->ComputeLoadField(
-            name, receiver, holder, lookup->GetFieldIndex());
-        break;
-      case CONSTANT_FUNCTION: {
-        Handle<JSFunction> constant(lookup->GetConstantFunction());
-        code = isolate()->stub_cache()->ComputeLoadConstant(
-            name, receiver, holder, constant);
-        break;
-      }
-      case NORMAL:
-        if (holder->IsGlobalObject()) {
-          Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
-          Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
-          code = isolate()->stub_cache()->ComputeLoadGlobal(
-              name, receiver, global, cell, lookup->IsDontDelete());
-        } else {
-          // There is only one shared stub for loading normalized
-          // properties. It does not traverse the prototype chain, so the
-          // property must be found in the receiver for the stub to be
-          // applicable.
-          if (!holder.is_identical_to(receiver)) return;
-          code = isolate()->stub_cache()->ComputeLoadNormal();
-        }
-        break;
-      case CALLBACKS: {
-        Handle<Object> callback(lookup->GetCallbackObject());
-        if (callback->IsAccessorInfo()) {
-          Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
-          if (v8::ToCData<Address>(info->getter()) == 0) return;
-          if (!info->IsCompatibleReceiver(*receiver)) return;
-          code = isolate()->stub_cache()->ComputeLoadCallback(
-              name, receiver, holder, info);
-        } else if (callback->IsAccessorPair()) {
-          Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
-          if (!getter->IsJSFunction()) return;
-          if (holder->IsGlobalObject()) return;
-          if (!holder->HasFastProperties()) return;
-          code = isolate()->stub_cache()->ComputeLoadViaGetter(
-              name, receiver, holder, Handle<JSFunction>::cast(getter));
-        } else {
-          ASSERT(callback->IsForeign());
-          // No IC support for old-style native accessors.
-          return;
-        }
-        break;
-      }
-      case INTERCEPTOR:
-        ASSERT(HasInterceptorGetter(*holder));
-        code = isolate()->stub_cache()->ComputeLoadInterceptor(
-            name, receiver, holder);
-        break;
-      default:
-        return;
-    }
+    code = ComputeLoadMonomorphic(lookup, receiver, name);
+    if (code.is_null()) return;
   }
 
   // Patch the call site depending on the state of the cache.
@@ -1062,17 +1002,14 @@ void LoadIC::UpdateLoadCaches(LookupResult* lookup,
         // the receiver into stub cache.
         Map* map = target()->FindFirstMap();
         if (map != NULL) {
-          isolate()->stub_cache()->Set(*name, map, target());
+          UpdateMegamorphicCache(map, *name, target());
         }
-        isolate()->stub_cache()->Set(*name, receiver->map(), *code);
-
+        UpdateMegamorphicCache(receiver->map(), *name, *code);
         set_target(*megamorphic_stub());
       }
       break;
     case MEGAMORPHIC:
-      // Cache code holding map should be consistent with
-      // GenerateMonomorphicCacheProbe.
-      isolate()->stub_cache()->Set(*name, receiver->map(), *code);
+      UpdateMegamorphicCache(receiver->map(), *name, *code);
       break;
     case DEBUG_STUB:
       break;
@@ -1086,6 +1023,76 @@ void LoadIC::UpdateLoadCaches(LookupResult* lookup,
 }
 
 
+void LoadIC::UpdateMegamorphicCache(Map* map, String* name, Code* code) {
+  // Cache code holding map should be consistent with
+  // GenerateMonomorphicCacheProbe.
+  isolate()->stub_cache()->Set(name, map, code);
+}
+
+
+Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
+                                            Handle<JSObject> receiver,
+                                            Handle<String> name) {
+  if (!lookup->IsProperty()) {
+    // Nonexistent property. The result is undefined.
+    return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
+  }
+
+  // Compute monomorphic stub.
+  Handle<JSObject> holder(lookup->holder());
+  switch (lookup->type()) {
+    case FIELD:
+      return isolate()->stub_cache()->ComputeLoadField(
+          name, receiver, holder, lookup->GetFieldIndex());
+    case CONSTANT_FUNCTION: {
+      Handle<JSFunction> constant(lookup->GetConstantFunction());
+      return isolate()->stub_cache()->ComputeLoadConstant(
+          name, receiver, holder, constant);
+    }
+    case NORMAL:
+      if (holder->IsGlobalObject()) {
+        Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
+        Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
+        return isolate()->stub_cache()->ComputeLoadGlobal(
+            name, receiver, global, cell, lookup->IsDontDelete());
+      }
+      // There is only one shared stub for loading normalized
+      // properties. It does not traverse the prototype chain, so the
+      // property must be found in the receiver for the stub to be
+      // applicable.
+      if (!holder.is_identical_to(receiver)) break;
+      return isolate()->stub_cache()->ComputeLoadNormal();
+    case CALLBACKS: {
+      Handle<Object> callback(lookup->GetCallbackObject());
+      if (callback->IsAccessorInfo()) {
+        Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
+        if (v8::ToCData<Address>(info->getter()) == 0) break;
+        if (!info->IsCompatibleReceiver(*receiver)) break;
+        return isolate()->stub_cache()->ComputeLoadCallback(
+            name, receiver, holder, info);
+      } else if (callback->IsAccessorPair()) {
+        Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
+        if (!getter->IsJSFunction()) break;
+        if (holder->IsGlobalObject()) break;
+        if (!holder->HasFastProperties()) break;
+        return isolate()->stub_cache()->ComputeLoadViaGetter(
+            name, receiver, holder, Handle<JSFunction>::cast(getter));
+      }
+      ASSERT(callback->IsForeign());
+      // No IC support for old-style native accessors.
+      break;
+    }
+    case INTERCEPTOR:
+      ASSERT(HasInterceptorGetter(*holder));
+      return isolate()->stub_cache()->ComputeLoadInterceptor(
+          name, receiver, holder);
+    default:
+      break;
+  }
+  return Handle<Code>::null();
+}
+
+
 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
   // This helper implements a few common fast cases for converting
   // non-smi keys of keyed loads/stores to a smi or a string.
@@ -1262,87 +1269,43 @@ MaybeObject* KeyedLoadIC::Load(State state,
 }
 
 
-void KeyedLoadIC::UpdateLoadCaches(LookupResult* lookup,
-                                   State state,
-                                   Handle<Object> object,
-                                   Handle<String> name) {
+Handle<Code> KeyedLoadIC::ComputeLoadMonomorphic(LookupResult* lookup,
+                                                 Handle<JSObject> receiver,
+                                                 Handle<String> name) {
   // Bail out if we didn't find a result.
-  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
-
-  if (!object->IsJSObject()) return;
-  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-
-  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
+  if (!lookup->IsProperty()) return Handle<Code>::null();
 
-  // Compute the code stub for this load.
-  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 {
-    // Compute a monomorphic stub.
-    Handle<JSObject> holder(lookup->holder());
-    switch (lookup->type()) {
-      case FIELD:
-        code = isolate()->stub_cache()->ComputeKeyedLoadField(
-            name, receiver, holder, lookup->GetFieldIndex());
-        break;
-      case CONSTANT_FUNCTION: {
-        Handle<JSFunction> constant(lookup->GetConstantFunction());
-        code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
-            name, receiver, holder, constant);
-        break;
-      }
-      case CALLBACKS: {
-        Handle<Object> callback_object(lookup->GetCallbackObject());
-        if (!callback_object->IsAccessorInfo()) return;
-        Handle<AccessorInfo> callback =
-            Handle<AccessorInfo>::cast(callback_object);
-        if (v8::ToCData<Address>(callback->getter()) == 0) return;
-        if (!callback->IsCompatibleReceiver(*receiver)) return;
-        code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
-            name, receiver, holder, callback);
-        break;
-      }
-      case INTERCEPTOR:
-        ASSERT(HasInterceptorGetter(lookup->holder()));
-        code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
-            name, receiver, holder);
-        break;
-      default:
-        // Always rewrite to the generic case so that we do not
-        // repeatedly try to rewrite.
-        code = generic_stub();
-        break;
+  // Compute a monomorphic stub.
+  Handle<JSObject> holder(lookup->holder());
+  switch (lookup->type()) {
+    case FIELD:
+      return isolate()->stub_cache()->ComputeKeyedLoadField(
+          name, receiver, holder, lookup->GetFieldIndex());
+    case CONSTANT_FUNCTION: {
+      Handle<JSFunction> constant(lookup->GetConstantFunction());
+      return isolate()->stub_cache()->ComputeKeyedLoadConstant(
+          name, receiver, holder, constant);
     }
+    case CALLBACKS: {
+      Handle<Object> callback_object(lookup->GetCallbackObject());
+      if (!callback_object->IsAccessorInfo()) break;
+      Handle<AccessorInfo> callback =
+          Handle<AccessorInfo>::cast(callback_object);
+      if (v8::ToCData<Address>(callback->getter()) == 0) break;
+      if (!callback->IsCompatibleReceiver(*receiver)) break;
+      return isolate()->stub_cache()->ComputeKeyedLoadCallback(
+          name, receiver, holder, callback);
+    }
+    case INTERCEPTOR:
+      ASSERT(HasInterceptorGetter(lookup->holder()));
+      return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
+          name, receiver, holder);
+    default:
+      // Always rewrite to the generic case so that we do not
+      // repeatedly try to rewrite.
+      return generic_stub();
   }
-
-  // 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(*megamorphic_stub());
-      }
-      break;
-    case MEGAMORPHIC:
-    case GENERIC:
-    case DEBUG_STUB:
-      break;
-    case MONOMORPHIC_PROTOTYPE_FAILURE:
-      UNREACHABLE();
-      break;
-  }
-
-  TRACE_IC("KeyedLoadIC", name, state, target());
+  return Handle<Code>::null();
 }
 
 
index 9acb72a..3ffe4e0 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -354,10 +354,14 @@ class LoadIC: public IC {
 
   // Update the inline cache and the global stub cache based on the
   // lookup result.
-  virtual void UpdateLoadCaches(LookupResult* lookup,
-                                State state,
-                                Handle<Object> object,
-                                Handle<String> name);
+  void UpdateCaches(LookupResult* lookup,
+                    State state,
+                    Handle<Object> object,
+                    Handle<String> name);
+  virtual Handle<Code> ComputeLoadMonomorphic(LookupResult* lookup,
+                                              Handle<JSObject> receiver,
+                                              Handle<String> name);
+  virtual void UpdateMegamorphicCache(Map* map, String* name, Code* code);
 
  private:
   // Stub accessors.
@@ -425,10 +429,10 @@ class KeyedLoadIC: public LoadIC {
   }
 
   // Update the inline cache.
-  virtual void UpdateLoadCaches(LookupResult* lookup,
-                                State state,
-                                Handle<Object> object,
-                                Handle<String> name);
+  virtual Handle<Code> ComputeLoadMonomorphic(LookupResult* lookup,
+                                              Handle<JSObject> receiver,
+                                              Handle<String> name);
+  virtual void UpdateMegamorphicCache(Map* map, String* name, Code* code) { }
 
  private:
   // Stub accessors.