Update V8 to r6387 as required by WebKit r76408

Change-Id: Icfc5385b0996bd592f8b1ac8cbb44767ee09f1f6
diff --git a/src/ic.cc b/src/ic.cc
index 645c6fd..afae323 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -154,24 +154,20 @@
 }
 
 
-IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
-  IC::State state = target->ic_state();
-
-  if (state != MONOMORPHIC || !name->IsString()) return state;
-  if (receiver->IsUndefined() || receiver->IsNull()) return state;
-
+static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
+                                                   Object* receiver,
+                                                   Object* name) {
   InlineCacheHolderFlag cache_holder =
       Code::ExtractCacheHolderFromFlags(target->flags());
 
-
   if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
     // The stub was generated for JSObject but called for non-JSObject.
     // IC::GetCodeCacheHolder is not applicable.
-    return MONOMORPHIC;
+    return false;
   } else if (cache_holder == PROTOTYPE_MAP &&
              receiver->GetPrototype()->IsNull()) {
     // IC::GetCodeCacheHolder is not applicable.
-    return MONOMORPHIC;
+    return false;
   }
   Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();
 
@@ -185,20 +181,37 @@
   // to prototype check failure.
   int index = map->IndexInCodeCache(name, target);
   if (index >= 0) {
-    // For keyed load/store/call, 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.
-    Code::Kind kind = target->kind();
-    if (kind == Code::KEYED_LOAD_IC ||
-        kind == Code::KEYED_STORE_IC ||
-        kind == Code::KEYED_CALL_IC) {
-      return MONOMORPHIC;
-    }
-
-    // Remove the target from the code cache to avoid hitting the same
-    // invalid stub again.
     map->RemoveFromCodeCache(String::cast(name), target, index);
+    return true;
+  }
 
+  return false;
+}
+
+
+IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
+  IC::State state = target->ic_state();
+
+  if (state != MONOMORPHIC || !name->IsString()) return state;
+  if (receiver->IsUndefined() || receiver->IsNull()) return state;
+
+  // For keyed load/store/call, 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.
+  Code::Kind kind = target->kind();
+  if (kind == Code::KEYED_LOAD_IC ||
+      kind == Code::KEYED_STORE_IC ||
+      kind == Code::KEYED_CALL_IC) {
+    return MONOMORPHIC;
+  }
+
+  // Remove the target from the code cache if it became invalid
+  // because of changes in the prototype chain to avoid hitting it
+  // again.
+  // Call stubs handle this later to allow extra IC state
+  // transitions.
+  if (kind != Code::CALL_IC &&
+      TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
     return MONOMORPHIC_PROTOTYPE_FAILURE;
   }
 
@@ -482,6 +495,7 @@
 
 
 MaybeObject* CallICBase::LoadFunction(State state,
+                                      Code::ExtraICState extra_ic_state,
                                       Handle<Object> object,
                                       Handle<String> name) {
   // If the object is undefined or null it's illegal to try to get any
@@ -527,7 +541,7 @@
 
   // Lookup is valid: Update inline cache and stub cache.
   if (FLAG_use_ic) {
-    UpdateCaches(&lookup, state, object, name);
+    UpdateCaches(&lookup, state, extra_ic_state, object, name);
   }
 
   // Get the property.
@@ -576,8 +590,142 @@
 }
 
 
+bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
+                                       Handle<Object> object,
+                                       Code::ExtraICState* extra_ic_state) {
+  ASSERT(kind_ == Code::CALL_IC);
+  if (lookup->type() != CONSTANT_FUNCTION) return false;
+  JSFunction* function = lookup->GetConstantFunction();
+  if (!function->shared()->HasBuiltinFunctionId()) return false;
+
+  // Fetch the arguments passed to the called function.
+  const int argc = target()->arguments_count();
+  Address entry = Top::c_entry_fp(Top::GetCurrentThread());
+  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
+  Arguments args(argc + 1,
+                 &Memory::Object_at(fp +
+                                    StandardFrameConstants::kCallerSPOffset +
+                                    argc * kPointerSize));
+  switch (function->shared()->builtin_function_id()) {
+    case kStringCharCodeAt:
+    case kStringCharAt:
+      if (object->IsString()) {
+        String* string = String::cast(*object);
+        // Check that there's the right wrapper in the receiver slot.
+        ASSERT(string == JSValue::cast(args[0])->value());
+        // If we're in the default (fastest) state and the index is
+        // out of bounds, update the state to record this fact.
+        if (*extra_ic_state == DEFAULT_STRING_STUB &&
+            argc >= 1 && args[1]->IsNumber()) {
+          double index;
+          if (args[1]->IsSmi()) {
+            index = Smi::cast(args[1])->value();
+          } else {
+            ASSERT(args[1]->IsHeapNumber());
+            index = DoubleToInteger(HeapNumber::cast(args[1])->value());
+          }
+          if (index < 0 || index >= string->length()) {
+            *extra_ic_state = STRING_INDEX_OUT_OF_BOUNDS;
+            return true;
+          }
+        }
+      }
+      break;
+    default:
+      return false;
+  }
+  return false;
+}
+
+
+MaybeObject* CallICBase::ComputeMonomorphicStub(
+    LookupResult* lookup,
+    State state,
+    Code::ExtraICState extra_ic_state,
+    Handle<Object> object,
+    Handle<String> name) {
+  int argc = target()->arguments_count();
+  InLoopFlag in_loop = target()->ic_in_loop();
+  MaybeObject* maybe_code = NULL;
+  switch (lookup->type()) {
+    case FIELD: {
+      int index = lookup->GetFieldIndex();
+      maybe_code = StubCache::ComputeCallField(argc,
+                                               in_loop,
+                                               kind_,
+                                               *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();
+      maybe_code = StubCache::ComputeCallConstant(argc,
+                                                  in_loop,
+                                                  kind_,
+                                                  extra_ic_state,
+                                                  *name,
+                                                  *object,
+                                                  lookup->holder(),
+                                                  function);
+      break;
+    }
+    case NORMAL: {
+      if (!object->IsJSObject()) return NULL;
+      Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+
+      if (lookup->holder()->IsGlobalObject()) {
+        GlobalObject* global = GlobalObject::cast(lookup->holder());
+        JSGlobalPropertyCell* cell =
+            JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
+        if (!cell->value()->IsJSFunction()) return NULL;
+        JSFunction* function = JSFunction::cast(cell->value());
+        maybe_code = StubCache::ComputeCallGlobal(argc,
+                                                  in_loop,
+                                                  kind_,
+                                                  *name,
+                                                  *receiver,
+                                                  global,
+                                                  cell,
+                                                  function);
+      } else {
+        // 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 (lookup->holder() != *receiver) return NULL;
+        maybe_code = StubCache::ComputeCallNormal(argc,
+                                                  in_loop,
+                                                  kind_,
+                                                  *name,
+                                                  *receiver);
+      }
+      break;
+    }
+    case INTERCEPTOR: {
+      ASSERT(HasInterceptorGetter(lookup->holder()));
+      maybe_code = StubCache::ComputeCallInterceptor(argc,
+                                                     kind_,
+                                                     *name,
+                                                     *object,
+                                                     lookup->holder());
+      break;
+    }
+    default:
+      maybe_code = NULL;
+      break;
+  }
+  return maybe_code;
+}
+
+
 void CallICBase::UpdateCaches(LookupResult* lookup,
                               State state,
+                              Code::ExtraICState extra_ic_state,
                               Handle<Object> object,
                               Handle<String> name) {
   // Bail out if we didn't find a result.
@@ -594,90 +742,44 @@
   int argc = target()->arguments_count();
   InLoopFlag in_loop = target()->ic_in_loop();
   MaybeObject* maybe_code = NULL;
-  Object* code;
+  bool had_proto_failure = false;
   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.
     maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
   } else if (state == MONOMORPHIC) {
-    maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
-  } else {
-    // Compute monomorphic stub.
-    switch (lookup->type()) {
-      case FIELD: {
-        int index = lookup->GetFieldIndex();
-        maybe_code = StubCache::ComputeCallField(argc,
-                                                 in_loop,
-                                                 kind_,
-                                                 *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();
-        maybe_code = StubCache::ComputeCallConstant(argc,
-                                                    in_loop,
-                                                    kind_,
-                                                    *name,
-                                                    *object,
-                                                    lookup->holder(),
-                                                    function);
-        break;
-      }
-      case NORMAL: {
-        if (!object->IsJSObject()) return;
-        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-
-        if (lookup->holder()->IsGlobalObject()) {
-          GlobalObject* global = GlobalObject::cast(lookup->holder());
-          JSGlobalPropertyCell* cell =
-              JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
-          if (!cell->value()->IsJSFunction()) return;
-          JSFunction* function = JSFunction::cast(cell->value());
-          maybe_code = StubCache::ComputeCallGlobal(argc,
-                                                    in_loop,
-                                                    kind_,
-                                                    *name,
-                                                    *receiver,
-                                                    global,
-                                                    cell,
-                                                    function);
-        } else {
-          // 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 (lookup->holder() != *receiver) return;
-          maybe_code = StubCache::ComputeCallNormal(argc,
-                                                    in_loop,
-                                                    kind_,
-                                                    *name,
-                                                    *receiver);
-        }
-        break;
-      }
-      case INTERCEPTOR: {
-        ASSERT(HasInterceptorGetter(lookup->holder()));
-        maybe_code = StubCache::ComputeCallInterceptor(argc,
-                                                       kind_,
-                                                       *name,
-                                                       *object,
-                                                       lookup->holder());
-        break;
-      }
-      default:
-        return;
+    if (kind_ == Code::CALL_IC &&
+        TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
+      maybe_code = ComputeMonomorphicStub(lookup,
+                                          state,
+                                          extra_ic_state,
+                                          object,
+                                          name);
+    } else if (kind_ == Code::CALL_IC &&
+               TryRemoveInvalidPrototypeDependentStub(target(),
+                                                      *object,
+                                                      *name)) {
+      had_proto_failure = true;
+      maybe_code = ComputeMonomorphicStub(lookup,
+                                          state,
+                                          extra_ic_state,
+                                          object,
+                                          name);
+    } else {
+      maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
     }
+  } else {
+    maybe_code = ComputeMonomorphicStub(lookup,
+                                        state,
+                                        extra_ic_state,
+                                        object,
+                                        name);
   }
 
   // If we're unable to compute the stub (not enough memory left), we
   // simply avoid updating the caches.
+  Object* code;
   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
 
   // Patch the call site depending on the state of the cache.
@@ -696,7 +798,9 @@
     StubCache::Set(*name, map, Code::cast(code));
   }
 
+  USE(had_proto_failure);
 #ifdef DEBUG
+  if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
   TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
       name, state, target(), in_loop ? " (in-loop)" : "");
 #endif
@@ -707,7 +811,10 @@
                                        Handle<Object> object,
                                        Handle<Object> key) {
   if (key->IsSymbol()) {
-    return CallICBase::LoadFunction(state, object, Handle<String>::cast(key));
+    return CallICBase::LoadFunction(state,
+                                    Code::kNoExtraICState,
+                                    object,
+                                    Handle<String>::cast(key));
   }
 
   if (object->IsUndefined() || object->IsNull()) {
@@ -1641,11 +1748,13 @@
   ASSERT(args.length() == 2);
   CallIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
+  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+  MaybeObject* maybe_result = ic.LoadFunction(state,
+                                              extra_ic_state,
+                                              args.at<Object>(0),
+                                              args.at<String>(1));
   Object* result;
-  { MaybeObject* maybe_result =
-       ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
+  if (!maybe_result->ToObject(&result)) return maybe_result;
 
   // The first time the inline cache is updated may be the first time the
   // function it references gets called.  If the function was lazily compiled