Author: [EMAIL PROTECTED]
Date: Thu Sep 18 03:22:46 2008
New Revision: 338

Modified:
    branches/bleeding_edge/src/ic.cc
    branches/bleeding_edge/src/ic.h
    branches/bleeding_edge/src/objects-inl.h
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h

Log:
Revert revision 331.  The propagation of monomorphic prototype failure
information does not work.  In certains situations, it will keep
alternating between unrelated monomorphic states instead of going
megamorphic.
Review URL: http://codereview.chromium.org/2959

Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc    (original)
+++ branches/bleeding_edge/src/ic.cc    Thu Sep 18 03:22:46 2008
@@ -61,7 +61,7 @@
                   State old_state,
                   Code* new_target) {
    if (FLAG_trace_ic) {
-    State new_state = new_target->ic_state();
+    State new_state = StateFrom(new_target, Heap::undefined_value());
      PrintF("[%s (%c->%c) ", type,
             TransitionMarkFromState(old_state),
             TransitionMarkFromState(new_state));
@@ -127,16 +127,11 @@
  }


-IC::State IC::ComputeCacheState(Code* target, Object* receiver,
-                                Object* name, Object** new_target) {
-  // Get the raw state from the target.
-  State target_state = target->ic_state();
+IC::State IC::StateFrom(Code* target, Object* receiver) {
+  IC::State state = target->ic_state();

-  // Assume that no new target exists in the cache.
-  *new_target = Heap::undefined_value();
-
-  if (target_state != MONOMORPHIC) return target_state;
-  if (receiver->IsUndefined() || receiver->IsNull()) return target_state;
+  if (state != MONOMORPHIC) return state;
+  if (receiver->IsUndefined() || receiver->IsNull()) return state;

    Map* map = GetCodeCacheMapForObject(receiver);

@@ -148,14 +143,8 @@
    // the receiver map's code cache.  Therefore, if the current target
    // is in the receiver map's code cache, the inline cache failed due
    // to prototype check failure.
-  int index = -1;
-  Object* code = NULL;
-  if (name->IsString()) {
-    code = map->FindIndexInCodeCache(String::cast(name),
-                                     target->flags(),
-                                     &index);
-  }
-  if (index >= 0 && code == target) {
+  int index = map->IndexInCodeCache(target);
+  if (index >= 0) {
      // For keyed load/store, the most likely cause of cache failure is
      // that the key has changed.  We do not distinguish between
      // prototype and non-prototype failures for keyed access.
@@ -183,7 +172,6 @@
      return UNINITIALIZED;
    }

-  *new_target = code;
    return MONOMORPHIC;
  }

@@ -287,7 +275,8 @@
  }


-Object* CallIC::LoadFunction(Handle<Object> object,
+Object* CallIC::LoadFunction(State state,
+                             Handle<Object> object,
                               Handle<String> name) {
    // If the object is undefined or null it's illegal to try to get any
    // of its properties; throw a TypeError in that case.
@@ -326,7 +315,7 @@

    // Lookup is valid: Update inline cache and stub cache.
    if (FLAG_use_ic && lookup.IsLoaded()) {
-    UpdateCaches(&lookup, object, name);
+    UpdateCaches(&lookup, state, object, name);
    }

    if (lookup.type() == INTERCEPTOR) {
@@ -385,6 +374,7 @@


  void CallIC::UpdateCaches(LookupResult* lookup,
+                          State state,
                            Handle<Object> object,
                            Handle<String> name) {
    ASSERT(lookup->IsLoaded());
@@ -393,55 +383,52 @@

    // Compute the number of arguments.
    int argc = target()->arguments_count();
+  Object* code = NULL;

-  Object* code = Heap::undefined_value();
-  State state = ComputeCacheState(target(), *object, *name, &code);
-
-  switch (state) {
-    case UNINITIALIZED:
-      code = StubCache::ComputeCallPreMonomorphic(argc);
-      break;
-    case MONOMORPHIC:
-      if (code->IsUndefined()) code =  
StubCache::ComputeCallMegamorphic(argc);
-      break;
-    default:
-      // Compute monomorphic stub.
-      switch (lookup->type()) {
-        case FIELD: {
-          int index = lookup->GetFieldIndex();
-          code = StubCache::ComputeCallField(argc, *name, *object,
-                                             lookup->holder(), index);
-          break;
-        }
-        case CONSTANT_FUNCTION: {
-          // Get the constant function and compute the code stub for this
-          // call; used for rewriting to monomorphic state and making sure
-          // that the code stub is in the stub cache.
-          JSFunction* function = lookup->GetConstantFunction();
-          code = StubCache::ComputeCallConstant(argc, *name, *object,
-                                                lookup->holder(),  
function);
-          break;
-        }
-        case NORMAL: {
-          // There is only one shared stub for calling 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 (!object->IsJSObject()) return;
-          Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-          if (lookup->holder() != *receiver) return;
-          code = StubCache::ComputeCallNormal(argc, *name, *receiver);
-          break;
-        }
-        case INTERCEPTOR: {
-          code = StubCache::ComputeCallInterceptor(argc, *name, *object,
-                                                   lookup->holder());
-          break;
-        }
-        default:
-          return;
+  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 = StubCache::ComputeCallPreMonomorphic(argc);
+  } else if (state == MONOMORPHIC) {
+    code = StubCache::ComputeCallMegamorphic(argc);
+  } else {
+    // Compute monomorphic stub.
+    switch (lookup->type()) {
+      case FIELD: {
+        int index = lookup->GetFieldIndex();
+        code = StubCache::ComputeCallField(argc, *name, *object,
+                                           lookup->holder(), index);
+        break;
        }
-      break;
+      case CONSTANT_FUNCTION: {
+        // Get the constant function and compute the code stub for this
+        // call; used for rewriting to monomorphic state and making sure
+        // that the code stub is in the stub cache.
+        JSFunction* function = lookup->GetConstantFunction();
+        code = StubCache::ComputeCallConstant(argc, *name, *object,
+                                              lookup->holder(), function);
+        break;
+      }
+      case NORMAL: {
+        // There is only one shared stub for calling 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 (!object->IsJSObject()) return;
+        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+        if (lookup->holder() != *receiver) return;
+        code = StubCache::ComputeCallNormal(argc, *name, *receiver);
+        break;
+      }
+      case INTERCEPTOR: {
+        code = StubCache::ComputeCallInterceptor(argc, *name, *object,
+                                                 lookup->holder());
+        break;
+      }
+      default:
+        return;
+    }
    }

    // If we're unable to compute the stub (not enough memory left), we
@@ -460,7 +447,7 @@
  }


-Object* LoadIC::Load(Handle<Object> object, Handle<String> name) {
+Object* LoadIC::Load(State state, Handle<Object> object, Handle<String>  
name) {
    // If the object is undefined or null it's illegal to try to get any
    // of its properties; throw a TypeError in that case.
    if (object->IsUndefined() || object->IsNull()) {
@@ -533,7 +520,7 @@

    // Update inline cache and stub cache.
    if (FLAG_use_ic && lookup.IsLoaded()) {
-    UpdateCaches(&lookup, object, name);
+    UpdateCaches(&lookup, state, object, name);
    }

    PropertyAttributes attr;
@@ -555,6 +542,7 @@


  void LoadIC::UpdateCaches(LookupResult* lookup,
+                          State state,
                            Handle<Object> object,
                            Handle<String> name) {
    ASSERT(lookup->IsLoaded());
@@ -567,15 +555,13 @@
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);

    // Compute the code stub for this load.
-  Object* code = Heap::undefined_value();
-  State state = ComputeCacheState(target(), *object, *name, &code);
-
+  Object* code = NULL;
    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 (state != MONOMORPHIC) {
+  } else {
      // Compute monomorphic stub.
      switch (lookup->type()) {
        case FIELD: {
@@ -616,20 +602,18 @@
        default:
          return;
      }
-
-    // If we're unable to compute the stub (not enough memory left), we
-    // simply avoid updating the caches.
-    if (code->IsFailure()) return;
    }

+  // If we're unable to compute the stub (not enough memory left), we
+  // simply avoid updating the caches.
+  if (code->IsFailure()) return;
+
    // Patch the call site depending on the state of the cache.
    if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
        state == MONOMORPHIC_PROTOTYPE_FAILURE) {
      set_target(Code::cast(code));
-  } else if (state == MONOMORPHIC && code->IsUndefined()) {
-    set_target(megamorphic_stub());
    } else if (state == MONOMORPHIC) {
-    set_target(Code::cast(code));
+    set_target(megamorphic_stub());
    }

  #ifdef DEBUG
@@ -638,7 +622,8 @@
  }


-Object* KeyedLoadIC::Load(Handle<Object> object,
+Object* KeyedLoadIC::Load(State state,
+                          Handle<Object> object,
                            Handle<Object> key) {
    if (key->IsSymbol()) {
      Handle<String> name = Handle<String>::cast(key);
@@ -666,7 +651,7 @@
          if (code->IsFailure()) return code;
          set_target(Code::cast(code));
  #ifdef DEBUG
-        if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /string]\n");
+        TraceIC("KeyedLoadIC", name, state, target());
  #endif
          return Smi::FromInt(string->length());
        }
@@ -678,7 +663,7 @@
          if (code->IsFailure()) return code;
          set_target(Code::cast(code));
  #ifdef DEBUG
-        if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#length /array]\n");
+        TraceIC("KeyedLoadIC", name, state, target());
  #endif
          return JSArray::cast(*object)->length();
        }
@@ -691,7 +676,7 @@
          if (code->IsFailure()) return code;
          set_target(Code::cast(code));
  #ifdef DEBUG
-        if (FLAG_trace_ic) PrintF("[KeyedLoadIC : +#prototype  
/function]\n");
+        TraceIC("KeyedLoadIC", name, state, target());
  #endif
          return Accessors::FunctionGetPrototype(*object, 0);
        }
@@ -720,7 +705,7 @@

      // Update the inline cache.
      if (FLAG_use_ic && lookup.IsLoaded()) {
-      UpdateCaches(&lookup, object, name);
+      UpdateCaches(&lookup, state, object, name);
      }

      PropertyAttributes attr;
@@ -750,9 +735,8 @@
  }


-void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
-                               Handle<Object> object,
-                               Handle<String> name) {
+void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
+                               Handle<Object> object, Handle<String> name)  
{
    ASSERT(lookup->IsLoaded());
    // Bail out if we didn't find a result.
    if (!lookup->IsValid() || !lookup->IsCacheable()) return;
@@ -760,11 +744,9 @@
    if (!object->IsJSObject()) return;
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);

-  // Compute the state of the current inline cache.
-  Object* code = Heap::undefined_value();
-  State state = ComputeCacheState(target(), *object, *name, &code);
-
    // Compute the code stub for this load.
+  Object* code = NULL;
+
    if (state == UNINITIALIZED) {
      // This is the first time we execute this inline cache.
      // Set the target to the pre monomorphic stub to delay
@@ -827,7 +809,8 @@
  }


-Object* StoreIC::Store(Handle<Object> object,
+Object* StoreIC::Store(State state,
+                       Handle<Object> object,
                         Handle<String> name,
                         Handle<Object> value) {
    // If the object is undefined or null it's illegal to try to set any
@@ -855,7 +838,7 @@

    // Update inline cache and stub cache.
    if (FLAG_use_ic && lookup.IsLoaded()) {
-    UpdateCaches(&lookup, receiver, name, value);
+    UpdateCaches(&lookup, state, receiver, name, value);
    }

    // Set the property.
@@ -864,6 +847,7 @@


  void StoreIC::UpdateCaches(LookupResult* lookup,
+                           State state,
                             Handle<JSObject> receiver,
                             Handle<String> name,
                             Handle<Object> value) {
@@ -880,13 +864,10 @@
    // current state.
    PropertyType type = lookup->type();

-  // Compute the state of the current inline cache.
-  Object* code = Heap::undefined_value();
-  State state = ComputeCacheState(target(), *receiver, *name, &code);
-
    // 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.
+  Object* code = NULL;
    switch (type) {
      case FIELD: {
        code = StubCache::ComputeStoreField(*name, *receiver,
@@ -936,7 +917,8 @@
  }


-Object* KeyedStoreIC::Store(Handle<Object> object,
+Object* KeyedStoreIC::Store(State state,
+                            Handle<Object> object,
                              Handle<Object> key,
                              Handle<Object> value) {
    if (key->IsSymbol()) {
@@ -967,7 +949,7 @@

      // Update inline cache and stub cache.
      if (FLAG_use_ic && lookup.IsLoaded()) {
-      UpdateCaches(&lookup, receiver, name, value);
+      UpdateCaches(&lookup, state, receiver, name, value);
      }

      // Set the property.
@@ -986,6 +968,7 @@


  void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
+                                State state,
                                  Handle<JSObject> receiver,
                                  Handle<String> name,
                                  Handle<Object> value) {
@@ -1005,8 +988,7 @@
    // 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.
-  Object* code = Heap::undefined_value();
-  State state = ComputeCacheState(target(), *receiver, *name, &code);
+  Object* code = NULL;

    switch (type) {
      case FIELD: {
@@ -1064,7 +1046,8 @@
    NoHandleAllocation na;
    ASSERT(args.length() == 2);
    CallIC ic;
-  return ic.LoadFunction(args.at<Object>(0), args.at<String>(1));
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
  }


@@ -1088,7 +1071,8 @@
    NoHandleAllocation na;
    ASSERT(args.length() == 2);
    LoadIC ic;
-  return ic.Load(args.at<Object>(0), args.at<String>(1));
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
  }


@@ -1107,7 +1091,8 @@
    NoHandleAllocation na;
    ASSERT(args.length() == 2);
    KeyedLoadIC ic;
-  return ic.Load(args.at<Object>(0), args.at<Object>(1));
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
  }


@@ -1126,7 +1111,9 @@
    NoHandleAllocation na;
    ASSERT(args.length() == 3);
    StoreIC ic;
-  return ic.Store(args.at<Object>(0), args.at<String>(1),  
args.at<Object>(2));
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Store(state, args.at<Object>(0), args.at<String>(1),
+                  args.at<Object>(2));
  }


@@ -1145,7 +1132,9 @@
    NoHandleAllocation na;
    ASSERT(args.length() == 3);
    KeyedStoreIC ic;
-  return ic.Store(args.at<Object>(0), args.at<Object>(1),  
args.at<Object>(2));
+  IC::State state = IC::StateFrom(ic.target(), args[0]);
+  return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
+                  args.at<Object>(2));
  }



Modified: branches/bleeding_edge/src/ic.h
==============================================================================
--- branches/bleeding_edge/src/ic.h     (original)
+++ branches/bleeding_edge/src/ic.h     Thu Sep 18 03:22:46 2008
@@ -81,12 +81,8 @@
    Code* target() { return GetTargetAtAddress(address()); }
    inline Address address();

-  // Compute the state of the current inline cache.  If the current
-  // inline cache is monomorphic, this might change the code cache in
-  // the receiver map and it might return a code object from the code
-  // cache in the receiver map that should be used as the new target.
-  static State ComputeCacheState(Code* target, Object* receiver,
-                                 Object* name, Object** new_target);
+  // Compute the current IC state based on the target stub and the  
receiver.
+  static State StateFrom(Code* target, Object* receiver);

    // Clear the inline cache to initial state.
    static void Clear(Address address);
@@ -165,7 +161,7 @@
   public:
    CallIC() : IC(EXTRA_CALL_FRAME) { ASSERT(target()->is_call_stub()); }

-  Object* LoadFunction(Handle<Object> object, Handle<String> name);
+  Object* LoadFunction(State state, Handle<Object> object, Handle<String>  
name);


    // Code generator routines.
@@ -183,6 +179,7 @@
    // Update the inline cache and the global stub cache based on the
    // lookup result.
    void UpdateCaches(LookupResult* lookup,
+                    State state,
                      Handle<Object> object,
                      Handle<String> name);

@@ -200,7 +197,7 @@
   public:
    LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }

-  Object* Load(Handle<Object> object, Handle<String> name);
+  Object* Load(State state, Handle<Object> object, Handle<String> name);

    // Code generator routines.
    static void GenerateInitialize(MacroAssembler* masm);
@@ -222,6 +219,7 @@
    // Update the inline cache and the global stub cache based on the
    // lookup result.
    void UpdateCaches(LookupResult* lookup,
+                    State state,
                      Handle<Object> object,
                      Handle<String> name);

@@ -245,7 +243,7 @@
   public:
    KeyedLoadIC() : IC(NO_EXTRA_FRAME) {  
ASSERT(target()->is_keyed_load_stub()); }

-  Object* Load(Handle<Object> object, Handle<Object> key);
+  Object* Load(State state, Handle<Object> object, Handle<Object> key);

    // Code generator routines.
    static void GenerateMiss(MacroAssembler* masm);
@@ -258,6 +256,7 @@

    // Update the inline cache.
    void UpdateCaches(LookupResult* lookup,
+                    State state,
                      Handle<Object> object,
                      Handle<String> name);

@@ -284,7 +283,8 @@
   public:
    StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }

-  Object* Store(Handle<Object> object,
+  Object* Store(State state,
+                Handle<Object> object,
                  Handle<String> name,
                  Handle<Object> value);

@@ -299,7 +299,7 @@
    // Update the inline cache and the global stub cache based on the
    // lookup result.
    void UpdateCaches(LookupResult* lookup,
-                    Handle<JSObject> receiver,
+                    State state, Handle<JSObject> receiver,
                      Handle<String> name,
                      Handle<Object> value);

@@ -320,7 +320,8 @@
   public:
    KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }

-  Object* Store(Handle<Object> object,
+  Object* Store(State state,
+                Handle<Object> object,
                  Handle<Object> name,
                  Handle<Object> value);

@@ -334,6 +335,7 @@

    // Update the inline cache.
    void UpdateCaches(LookupResult* lookup,
+                    State state,
                      Handle<JSObject> receiver,
                      Handle<String> name,
                      Handle<Object> value);

Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h    (original)
+++ branches/bleeding_edge/src/objects-inl.h    Thu Sep 18 03:22:46 2008
@@ -2109,20 +2109,6 @@
  }


-Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
-  int index;
-  return FindIndexInCodeCache(name, flags, &index);
-}
-
-
-void Map::RemoveFromCodeCache(int index) {
-  FixedArray* array = code_cache();
-  ASSERT(array->length() >= index && array->get(index)->IsCode());
-  array->set_undefined(index - 1);  // key
-  array->set_undefined(index);  // code
-}
-
-
  #undef CAST_ACCESSOR
  #undef INT_ACCESSORS
  #undef SMI_ACCESSORS

Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Thu Sep 18 03:22:46 2008
@@ -2410,24 +2410,38 @@
  }


-Object* Map::FindIndexInCodeCache(String* name, Code::Flags flags, int*  
index) {
+Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
    FixedArray* cache = code_cache();
    int length = cache->length();
    for (int i = 0; i < length; i += 2) {
      Object* key = cache->get(i);
      if (key->IsUndefined()) {
-      continue;
+      return key;
      }
      if (name->Equals(String::cast(key))) {
        Code* code = Code::cast(cache->get(i + 1));
-      if (code->flags() == flags) {
-        *index = i + 1;
-        return code;
-      }
+      if (code->flags() == flags) return code;
      }
    }
-  *index = -1;
    return Heap::undefined_value();
+}
+
+
+int Map::IndexInCodeCache(Code* code) {
+  FixedArray* array = code_cache();
+  int len = array->length();
+  for (int i = 0; i < len; i += 2) {
+    if (array->get(i + 1) == code) return i + 1;
+  }
+  return -1;
+}
+
+
+void Map::RemoveFromCodeCache(int index) {
+  FixedArray* array = code_cache();
+  ASSERT(array->length() >= index && array->get(index)->IsCode());
+  array->set_undefined(index - 1);  // key
+  array->set_undefined(index);  // code
  }



Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Thu Sep 18 03:22:46 2008
@@ -2342,14 +2342,14 @@
    Object* UpdateCodeCache(String* name, Code* code);

    // Returns the found code or undefined if absent.
-  inline Object* FindInCodeCache(String* name, Code::Flags flags);
+  Object* FindInCodeCache(String* name, Code::Flags flags);

-  // Returns the found code or undefined if absent.  Also returns the
-  // index at which the code was found or -1 if absent.
-  Object* FindIndexInCodeCache(String* name, Code::Flags flags, int*  
index);
+  // Returns the non-negative index of the code object if it is in the
+  // cache and -1 otherwise.
+  int IndexInCodeCache(Code* code);

    // Removes a code object from the code cache at the given index.
-  inline void RemoveFromCodeCache(int index);
+  void RemoveFromCodeCache(int index);

    // Dispatched behavior.
    void MapIterateBody(ObjectVisitor* v);

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

Reply via email to