Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #include "accessors.h"
     31 #include "api.h"
     32 #include "arguments.h"
     33 #include "codegen.h"
     34 #include "execution.h"
     35 #include "ic-inl.h"
     36 #include "runtime.h"
     37 #include "stub-cache.h"
     38 
     39 namespace v8 {
     40 namespace internal {
     41 
     42 #ifdef DEBUG
     43 static char TransitionMarkFromState(IC::State state) {
     44   switch (state) {
     45     case UNINITIALIZED: return '0';
     46     case PREMONOMORPHIC: return 'P';
     47     case MONOMORPHIC: return '1';
     48     case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
     49     case MEGAMORPHIC: return 'N';
     50 
     51     // We never see the debugger states here, because the state is
     52     // computed from the original code - not the patched code. Let
     53     // these cases fall through to the unreachable code below.
     54     case DEBUG_BREAK: break;
     55     case DEBUG_PREPARE_STEP_IN: break;
     56   }
     57   UNREACHABLE();
     58   return 0;
     59 }
     60 
     61 void IC::TraceIC(const char* type,
     62                  Handle<Object> name,
     63                  State old_state,
     64                  Code* new_target,
     65                  const char* extra_info) {
     66   if (FLAG_trace_ic) {
     67     State new_state = StateFrom(new_target,
     68                                 HEAP->undefined_value(),
     69                                 HEAP->undefined_value());
     70     PrintF("[%s (%c->%c)%s", type,
     71            TransitionMarkFromState(old_state),
     72            TransitionMarkFromState(new_state),
     73            extra_info);
     74     name->Print();
     75     PrintF("]\n");
     76   }
     77 }
     78 #endif
     79 
     80 
     81 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
     82   ASSERT(isolate == Isolate::Current());
     83   // To improve the performance of the (much used) IC code, we unfold
     84   // a few levels of the stack frame iteration code. This yields a
     85   // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
     86   const Address entry =
     87       Isolate::c_entry_fp(isolate->thread_local_top());
     88   Address* pc_address =
     89       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
     90   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
     91   // If there's another JavaScript frame on the stack, we need to look
     92   // one frame further down the stack to find the frame pointer and
     93   // the return address stack slot.
     94   if (depth == EXTRA_CALL_FRAME) {
     95     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
     96     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
     97     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
     98   }
     99 #ifdef DEBUG
    100   StackFrameIterator it;
    101   for (int i = 0; i < depth + 1; i++) it.Advance();
    102   StackFrame* frame = it.frame();
    103   ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
    104 #endif
    105   fp_ = fp;
    106   pc_address_ = pc_address;
    107 }
    108 
    109 
    110 #ifdef ENABLE_DEBUGGER_SUPPORT
    111 Address IC::OriginalCodeAddress() {
    112   HandleScope scope;
    113   // Compute the JavaScript frame for the frame pointer of this IC
    114   // structure. We need this to be able to find the function
    115   // corresponding to the frame.
    116   StackFrameIterator it;
    117   while (it.frame()->fp() != this->fp()) it.Advance();
    118   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
    119   // Find the function on the stack and both the active code for the
    120   // function and the original code.
    121   JSFunction* function = JSFunction::cast(frame->function());
    122   Handle<SharedFunctionInfo> shared(function->shared());
    123   Code* code = shared->code();
    124   ASSERT(Debug::HasDebugInfo(shared));
    125   Code* original_code = Debug::GetDebugInfo(shared)->original_code();
    126   ASSERT(original_code->IsCode());
    127   // Get the address of the call site in the active code. This is the
    128   // place where the call to DebugBreakXXX is and where the IC
    129   // normally would be.
    130   Address addr = pc() - Assembler::kCallTargetAddressOffset;
    131   // Return the address in the original code. This is the place where
    132   // the call which has been overwritten by the DebugBreakXXX resides
    133   // and the place where the inline cache system should look.
    134   intptr_t delta =
    135       original_code->instruction_start() - code->instruction_start();
    136   return addr + delta;
    137 }
    138 #endif
    139 
    140 
    141 static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
    142                                              LookupResult* lookup,
    143                                              Object* receiver) {
    144   Object* end = lookup->IsProperty()
    145       ? lookup->holder() : isolate->heap()->null_value();
    146   for (Object* current = receiver;
    147        current != end;
    148        current = current->GetPrototype()) {
    149     if (current->IsJSObject() &&
    150         !JSObject::cast(current)->HasFastProperties() &&
    151         !current->IsJSGlobalProxy() &&
    152         !current->IsJSGlobalObject()) {
    153       return true;
    154     }
    155   }
    156 
    157   return false;
    158 }
    159 
    160 
    161 static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
    162                                                    Object* receiver,
    163                                                    Object* name) {
    164   InlineCacheHolderFlag cache_holder =
    165       Code::ExtractCacheHolderFromFlags(target->flags());
    166 
    167   if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
    168     // The stub was generated for JSObject but called for non-JSObject.
    169     // IC::GetCodeCacheHolder is not applicable.
    170     return false;
    171   } else if (cache_holder == PROTOTYPE_MAP &&
    172              receiver->GetPrototype()->IsNull()) {
    173     // IC::GetCodeCacheHolder is not applicable.
    174     return false;
    175   }
    176   Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();
    177 
    178   // Decide whether the inline cache failed because of changes to the
    179   // receiver itself or changes to one of its prototypes.
    180   //
    181   // If there are changes to the receiver itself, the map of the
    182   // receiver will have changed and the current target will not be in
    183   // the receiver map's code cache.  Therefore, if the current target
    184   // is in the receiver map's code cache, the inline cache failed due
    185   // to prototype check failure.
    186   int index = map->IndexInCodeCache(name, target);
    187   if (index >= 0) {
    188     map->RemoveFromCodeCache(String::cast(name), target, index);
    189     return true;
    190   }
    191 
    192   return false;
    193 }
    194 
    195 
    196 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
    197   IC::State state = target->ic_state();
    198 
    199   if (state != MONOMORPHIC || !name->IsString()) return state;
    200   if (receiver->IsUndefined() || receiver->IsNull()) return state;
    201 
    202   // For keyed load/store/call, the most likely cause of cache failure is
    203   // that the key has changed.  We do not distinguish between
    204   // prototype and non-prototype failures for keyed access.
    205   Code::Kind kind = target->kind();
    206   if (kind == Code::KEYED_LOAD_IC ||
    207       kind == Code::KEYED_STORE_IC ||
    208       kind == Code::KEYED_CALL_IC) {
    209     return MONOMORPHIC;
    210   }
    211 
    212   // Remove the target from the code cache if it became invalid
    213   // because of changes in the prototype chain to avoid hitting it
    214   // again.
    215   // Call stubs handle this later to allow extra IC state
    216   // transitions.
    217   if (kind != Code::CALL_IC &&
    218       TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
    219     return MONOMORPHIC_PROTOTYPE_FAILURE;
    220   }
    221 
    222   // The builtins object is special.  It only changes when JavaScript
    223   // builtins are loaded lazily.  It is important to keep inline
    224   // caches for the builtins object monomorphic.  Therefore, if we get
    225   // an inline cache miss for the builtins object after lazily loading
    226   // JavaScript builtins, we return uninitialized as the state to
    227   // force the inline cache back to monomorphic state.
    228   if (receiver->IsJSBuiltinsObject()) {
    229     return UNINITIALIZED;
    230   }
    231 
    232   return MONOMORPHIC;
    233 }
    234 
    235 
    236 RelocInfo::Mode IC::ComputeMode() {
    237   Address addr = address();
    238   Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
    239   for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
    240        !it.done(); it.next()) {
    241     RelocInfo* info = it.rinfo();
    242     if (info->pc() == addr) return info->rmode();
    243   }
    244   UNREACHABLE();
    245   return RelocInfo::NONE;
    246 }
    247 
    248 
    249 Failure* IC::TypeError(const char* type,
    250                        Handle<Object> object,
    251                        Handle<Object> key) {
    252   HandleScope scope(isolate());
    253   Handle<Object> args[2] = { key, object };
    254   Handle<Object> error = isolate()->factory()->NewTypeError(
    255       type, HandleVector(args, 2));
    256   return isolate()->Throw(*error);
    257 }
    258 
    259 
    260 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
    261   HandleScope scope(isolate());
    262   Handle<Object> error = isolate()->factory()->NewReferenceError(
    263       type, HandleVector(&name, 1));
    264   return isolate()->Throw(*error);
    265 }
    266 
    267 
    268 void IC::Clear(Address address) {
    269   Code* target = GetTargetAtAddress(address);
    270 
    271   // Don't clear debug break inline cache as it will remove the break point.
    272   if (target->ic_state() == DEBUG_BREAK) return;
    273 
    274   switch (target->kind()) {
    275     case Code::LOAD_IC: return LoadIC::Clear(address, target);
    276     case Code::KEYED_LOAD_IC:
    277     case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
    278       return KeyedLoadIC::Clear(address, target);
    279     case Code::STORE_IC: return StoreIC::Clear(address, target);
    280     case Code::KEYED_STORE_IC:
    281     case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
    282       return KeyedStoreIC::Clear(address, target);
    283     case Code::CALL_IC: return CallIC::Clear(address, target);
    284     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
    285     case Code::TYPE_RECORDING_BINARY_OP_IC:
    286     case Code::COMPARE_IC:
    287       // Clearing these is tricky and does not
    288       // make any performance difference.
    289       return;
    290     default: UNREACHABLE();
    291   }
    292 }
    293 
    294 
    295 void CallICBase::Clear(Address address, Code* target) {
    296   State state = target->ic_state();
    297   if (state == UNINITIALIZED) return;
    298   Code* code =
    299       Isolate::Current()->stub_cache()->FindCallInitialize(
    300           target->arguments_count(),
    301           target->ic_in_loop(),
    302           target->kind());
    303   SetTargetAtAddress(address, code);
    304 }
    305 
    306 
    307 void KeyedLoadIC::ClearInlinedVersion(Address address) {
    308   // Insert null as the map to check for to make sure the map check fails
    309   // sending control flow to the IC instead of the inlined version.
    310   PatchInlinedLoad(address, HEAP->null_value());
    311 }
    312 
    313 
    314 void KeyedLoadIC::Clear(Address address, Code* target) {
    315   if (target->ic_state() == UNINITIALIZED) return;
    316   // Make sure to also clear the map used in inline fast cases.  If we
    317   // do not clear these maps, cached code can keep objects alive
    318   // through the embedded maps.
    319   ClearInlinedVersion(address);
    320   SetTargetAtAddress(address, initialize_stub());
    321 }
    322 
    323 
    324 void LoadIC::ClearInlinedVersion(Address address) {
    325   // Reset the map check of the inlined inobject property load (if
    326   // present) to guarantee failure by holding an invalid map (the null
    327   // value).  The offset can be patched to anything.
    328   Heap* heap = HEAP;
    329   PatchInlinedLoad(address, heap->null_value(), 0);
    330   PatchInlinedContextualLoad(address,
    331                              heap->null_value(),
    332                              heap->null_value(),
    333                              true);
    334 }
    335 
    336 
    337 void LoadIC::Clear(Address address, Code* target) {
    338   if (target->ic_state() == UNINITIALIZED) return;
    339   ClearInlinedVersion(address);
    340   SetTargetAtAddress(address, initialize_stub());
    341 }
    342 
    343 
    344 void StoreIC::ClearInlinedVersion(Address address) {
    345   // Reset the map check of the inlined inobject property store (if
    346   // present) to guarantee failure by holding an invalid map (the null
    347   // value).  The offset can be patched to anything.
    348   PatchInlinedStore(address, HEAP->null_value(), 0);
    349 }
    350 
    351 
    352 void StoreIC::Clear(Address address, Code* target) {
    353   if (target->ic_state() == UNINITIALIZED) return;
    354   ClearInlinedVersion(address);
    355   SetTargetAtAddress(address,
    356       (target->extra_ic_state() == kStrictMode)
    357         ? initialize_stub_strict()
    358         : initialize_stub());
    359 }
    360 
    361 
    362 void KeyedStoreIC::ClearInlinedVersion(Address address) {
    363   // Insert null as the elements map to check for.  This will make
    364   // sure that the elements fast-case map check fails so that control
    365   // flows to the IC instead of the inlined version.
    366   PatchInlinedStore(address, HEAP->null_value());
    367 }
    368 
    369 
    370 void KeyedStoreIC::RestoreInlinedVersion(Address address) {
    371   // Restore the fast-case elements map check so that the inlined
    372   // version can be used again.
    373   PatchInlinedStore(address, HEAP->fixed_array_map());
    374 }
    375 
    376 
    377 void KeyedStoreIC::Clear(Address address, Code* target) {
    378   if (target->ic_state() == UNINITIALIZED) return;
    379   SetTargetAtAddress(address,
    380       (target->extra_ic_state() == kStrictMode)
    381         ? initialize_stub_strict()
    382         : initialize_stub());
    383 }
    384 
    385 
    386 static bool HasInterceptorGetter(JSObject* object) {
    387   return !object->GetNamedInterceptor()->getter()->IsUndefined();
    388 }
    389 
    390 
    391 static void LookupForRead(Object* object,
    392                           String* name,
    393                           LookupResult* lookup) {
    394   AssertNoAllocation no_gc;  // pointers must stay valid
    395 
    396   // Skip all the objects with named interceptors, but
    397   // without actual getter.
    398   while (true) {
    399     object->Lookup(name, lookup);
    400     // Besides normal conditions (property not found or it's not
    401     // an interceptor), bail out if lookup is not cacheable: we won't
    402     // be able to IC it anyway and regular lookup should work fine.
    403     if (!lookup->IsFound()
    404         || (lookup->type() != INTERCEPTOR)
    405         || !lookup->IsCacheable()) {
    406       return;
    407     }
    408 
    409     JSObject* holder = lookup->holder();
    410     if (HasInterceptorGetter(holder)) {
    411       return;
    412     }
    413 
    414     holder->LocalLookupRealNamedProperty(name, lookup);
    415     if (lookup->IsProperty()) {
    416       ASSERT(lookup->type() != INTERCEPTOR);
    417       return;
    418     }
    419 
    420     Object* proto = holder->GetPrototype();
    421     if (proto->IsNull()) {
    422       lookup->NotFound();
    423       return;
    424     }
    425 
    426     object = proto;
    427   }
    428 }
    429 
    430 
    431 Object* CallICBase::TryCallAsFunction(Object* object) {
    432   HandleScope scope(isolate());
    433   Handle<Object> target(object, isolate());
    434   Handle<Object> delegate = Execution::GetFunctionDelegate(target);
    435 
    436   if (delegate->IsJSFunction()) {
    437     // Patch the receiver and use the delegate as the function to
    438     // invoke. This is used for invoking objects as if they were
    439     // functions.
    440     const int argc = this->target()->arguments_count();
    441     StackFrameLocator locator;
    442     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    443     int index = frame->ComputeExpressionsCount() - (argc + 1);
    444     frame->SetExpression(index, *target);
    445   }
    446 
    447   return *delegate;
    448 }
    449 
    450 
    451 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
    452                                             Handle<Object> object) {
    453   if (callee->IsJSFunction()) {
    454     Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
    455     if (function->shared()->strict_mode() || function->IsBuiltin()) {
    456       // Do not wrap receiver for strict mode functions or for builtins.
    457       return;
    458     }
    459   }
    460 
    461   // And only wrap string, number or boolean.
    462   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
    463     // Change the receiver to the result of calling ToObject on it.
    464     const int argc = this->target()->arguments_count();
    465     StackFrameLocator locator;
    466     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    467     int index = frame->ComputeExpressionsCount() - (argc + 1);
    468     frame->SetExpression(index, *isolate()->factory()->ToObject(object));
    469   }
    470 }
    471 
    472 
    473 MaybeObject* CallICBase::LoadFunction(State state,
    474                                       Code::ExtraICState extra_ic_state,
    475                                       Handle<Object> object,
    476                                       Handle<String> name) {
    477   // If the object is undefined or null it's illegal to try to get any
    478   // of its properties; throw a TypeError in that case.
    479   if (object->IsUndefined() || object->IsNull()) {
    480     return TypeError("non_object_property_call", object, name);
    481   }
    482 
    483   // Check if the name is trivially convertible to an index and get
    484   // the element if so.
    485   uint32_t index;
    486   if (name->AsArrayIndex(&index)) {
    487     Object* result;
    488     { MaybeObject* maybe_result = object->GetElement(index);
    489       if (!maybe_result->ToObject(&result)) return maybe_result;
    490     }
    491 
    492     if (result->IsJSFunction()) return result;
    493 
    494     // Try to find a suitable function delegate for the object at hand.
    495     result = TryCallAsFunction(result);
    496     if (result->IsJSFunction()) return result;
    497 
    498     // Otherwise, it will fail in the lookup step.
    499   }
    500 
    501   // Lookup the property in the object.
    502   LookupResult lookup;
    503   LookupForRead(*object, *name, &lookup);
    504 
    505   if (!lookup.IsProperty()) {
    506     // If the object does not have the requested property, check which
    507     // exception we need to throw.
    508     if (IsContextual(object)) {
    509       return ReferenceError("not_defined", name);
    510     }
    511     return TypeError("undefined_method", object, name);
    512   }
    513 
    514   // Lookup is valid: Update inline cache and stub cache.
    515   if (FLAG_use_ic) {
    516     UpdateCaches(&lookup, state, extra_ic_state, object, name);
    517   }
    518 
    519   // Get the property.
    520   PropertyAttributes attr;
    521   Object* result;
    522   { MaybeObject* maybe_result =
    523         object->GetProperty(*object, &lookup, *name, &attr);
    524     if (!maybe_result->ToObject(&result)) return maybe_result;
    525   }
    526 
    527   if (lookup.type() == INTERCEPTOR) {
    528     // If the object does not have the requested property, check which
    529     // exception we need to throw.
    530     if (attr == ABSENT) {
    531       if (IsContextual(object)) {
    532         return ReferenceError("not_defined", name);
    533       }
    534       return TypeError("undefined_method", object, name);
    535     }
    536   }
    537 
    538   ASSERT(!result->IsTheHole());
    539 
    540   HandleScope scope(isolate());
    541   // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
    542   // new object and cause GC.
    543   Handle<Object> result_handle(result);
    544   // Make receiver an object if the callee requires it. Strict mode or builtin
    545   // functions do not wrap the receiver, non-strict functions and objects
    546   // called as functions do.
    547   ReceiverToObjectIfRequired(result_handle, object);
    548 
    549   if (result_handle->IsJSFunction()) {
    550 #ifdef ENABLE_DEBUGGER_SUPPORT
    551     // Handle stepping into a function if step into is active.
    552     Debug* debug = isolate()->debug();
    553     if (debug->StepInActive()) {
    554       // Protect the result in a handle as the debugger can allocate and might
    555       // cause GC.
    556       Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
    557       debug->HandleStepIn(function, object, fp(), false);
    558       return *function;
    559     }
    560 #endif
    561 
    562     return *result_handle;
    563   }
    564 
    565   // Try to find a suitable function delegate for the object at hand.
    566   result_handle = Handle<Object>(TryCallAsFunction(*result_handle));
    567   if (result_handle->IsJSFunction()) return *result_handle;
    568 
    569   return TypeError("property_not_function", object, name);
    570 }
    571 
    572 
    573 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
    574                                        Handle<Object> object,
    575                                        Code::ExtraICState* extra_ic_state) {
    576   ASSERT(kind_ == Code::CALL_IC);
    577   if (lookup->type() != CONSTANT_FUNCTION) return false;
    578   JSFunction* function = lookup->GetConstantFunction();
    579   if (!function->shared()->HasBuiltinFunctionId()) return false;
    580 
    581   // Fetch the arguments passed to the called function.
    582   const int argc = target()->arguments_count();
    583   Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
    584   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
    585   Arguments args(argc + 1,
    586                  &Memory::Object_at(fp +
    587                                     StandardFrameConstants::kCallerSPOffset +
    588                                     argc * kPointerSize));
    589   switch (function->shared()->builtin_function_id()) {
    590     case kStringCharCodeAt:
    591     case kStringCharAt:
    592       if (object->IsString()) {
    593         String* string = String::cast(*object);
    594         // Check there's the right string value or wrapper in the receiver slot.
    595         ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
    596         // If we're in the default (fastest) state and the index is
    597         // out of bounds, update the state to record this fact.
    598         if (*extra_ic_state == DEFAULT_STRING_STUB &&
    599             argc >= 1 && args[1]->IsNumber()) {
    600           double index;
    601           if (args[1]->IsSmi()) {
    602             index = Smi::cast(args[1])->value();
    603           } else {
    604             ASSERT(args[1]->IsHeapNumber());
    605             index = DoubleToInteger(HeapNumber::cast(args[1])->value());
    606           }
    607           if (index < 0 || index >= string->length()) {
    608             *extra_ic_state = STRING_INDEX_OUT_OF_BOUNDS;
    609             return true;
    610           }
    611         }
    612       }
    613       break;
    614     default:
    615       return false;
    616   }
    617   return false;
    618 }
    619 
    620 
    621 MaybeObject* CallICBase::ComputeMonomorphicStub(
    622     LookupResult* lookup,
    623     State state,
    624     Code::ExtraICState extra_ic_state,
    625     Handle<Object> object,
    626     Handle<String> name) {
    627   int argc = target()->arguments_count();
    628   InLoopFlag in_loop = target()->ic_in_loop();
    629   MaybeObject* maybe_code = NULL;
    630   switch (lookup->type()) {
    631     case FIELD: {
    632       int index = lookup->GetFieldIndex();
    633       maybe_code = isolate()->stub_cache()->ComputeCallField(argc,
    634                                                              in_loop,
    635                                                              kind_,
    636                                                              *name,
    637                                                              *object,
    638                                                              lookup->holder(),
    639                                                              index);
    640       break;
    641     }
    642     case CONSTANT_FUNCTION: {
    643       // Get the constant function and compute the code stub for this
    644       // call; used for rewriting to monomorphic state and making sure
    645       // that the code stub is in the stub cache.
    646       JSFunction* function = lookup->GetConstantFunction();
    647       maybe_code =
    648           isolate()->stub_cache()->ComputeCallConstant(argc,
    649                                                        in_loop,
    650                                                        kind_,
    651                                                        extra_ic_state,
    652                                                        *name,
    653                                                        *object,
    654                                                        lookup->holder(),
    655                                                        function);
    656       break;
    657     }
    658     case NORMAL: {
    659       if (!object->IsJSObject()) return NULL;
    660       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    661 
    662       if (lookup->holder()->IsGlobalObject()) {
    663         GlobalObject* global = GlobalObject::cast(lookup->holder());
    664         JSGlobalPropertyCell* cell =
    665             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
    666         if (!cell->value()->IsJSFunction()) return NULL;
    667         JSFunction* function = JSFunction::cast(cell->value());
    668         maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc,
    669                                                                 in_loop,
    670                                                                 kind_,
    671                                                                 *name,
    672                                                                 *receiver,
    673                                                                 global,
    674                                                                 cell,
    675                                                                 function);
    676       } else {
    677         // There is only one shared stub for calling normalized
    678         // properties. It does not traverse the prototype chain, so the
    679         // property must be found in the receiver for the stub to be
    680         // applicable.
    681         if (lookup->holder() != *receiver) return NULL;
    682         maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc,
    683                                                                 in_loop,
    684                                                                 kind_,
    685                                                                 *name,
    686                                                                 *receiver);
    687       }
    688       break;
    689     }
    690     case INTERCEPTOR: {
    691       ASSERT(HasInterceptorGetter(lookup->holder()));
    692       maybe_code = isolate()->stub_cache()->ComputeCallInterceptor(
    693           argc,
    694           kind_,
    695           *name,
    696           *object,
    697           lookup->holder());
    698       break;
    699     }
    700     default:
    701       maybe_code = NULL;
    702       break;
    703   }
    704   return maybe_code;
    705 }
    706 
    707 
    708 void CallICBase::UpdateCaches(LookupResult* lookup,
    709                               State state,
    710                               Code::ExtraICState extra_ic_state,
    711                               Handle<Object> object,
    712                               Handle<String> name) {
    713   // Bail out if we didn't find a result.
    714   if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
    715 
    716   if (lookup->holder() != *object &&
    717       HasNormalObjectsInPrototypeChain(
    718           isolate(), lookup, object->GetPrototype())) {
    719     // Suppress optimization for prototype chains with slow properties objects
    720     // in the middle.
    721     return;
    722   }
    723 
    724   // Compute the number of arguments.
    725   int argc = target()->arguments_count();
    726   InLoopFlag in_loop = target()->ic_in_loop();
    727   MaybeObject* maybe_code = NULL;
    728   bool had_proto_failure = false;
    729   if (state == UNINITIALIZED) {
    730     // This is the first time we execute this inline cache.
    731     // Set the target to the pre monomorphic stub to delay
    732     // setting the monomorphic state.
    733     maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc,
    734                                                                     in_loop,
    735                                                                     kind_);
    736   } else if (state == MONOMORPHIC) {
    737     if (kind_ == Code::CALL_IC &&
    738         TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
    739       maybe_code = ComputeMonomorphicStub(lookup,
    740                                           state,
    741                                           extra_ic_state,
    742                                           object,
    743                                           name);
    744     } else if (kind_ == Code::CALL_IC &&
    745                TryRemoveInvalidPrototypeDependentStub(target(),
    746                                                       *object,
    747                                                       *name)) {
    748       had_proto_failure = true;
    749       maybe_code = ComputeMonomorphicStub(lookup,
    750                                           state,
    751                                           extra_ic_state,
    752                                           object,
    753                                           name);
    754     } else {
    755       maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc,
    756                                                                    in_loop,
    757                                                                    kind_);
    758     }
    759   } else {
    760     maybe_code = ComputeMonomorphicStub(lookup,
    761                                         state,
    762                                         extra_ic_state,
    763                                         object,
    764                                         name);
    765   }
    766 
    767   // If we're unable to compute the stub (not enough memory left), we
    768   // simply avoid updating the caches.
    769   Object* code;
    770   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
    771 
    772   // Patch the call site depending on the state of the cache.
    773   if (state == UNINITIALIZED ||
    774       state == PREMONOMORPHIC ||
    775       state == MONOMORPHIC ||
    776       state == MONOMORPHIC_PROTOTYPE_FAILURE) {
    777     set_target(Code::cast(code));
    778   } else if (state == MEGAMORPHIC) {
    779     // Cache code holding map should be consistent with
    780     // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
    781     Map* map = JSObject::cast(object->IsJSObject() ? *object :
    782                               object->GetPrototype())->map();
    783 
    784     // Update the stub cache.
    785     isolate()->stub_cache()->Set(*name, map, Code::cast(code));
    786   }
    787 
    788   USE(had_proto_failure);
    789 #ifdef DEBUG
    790   if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
    791   TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
    792       name, state, target(), in_loop ? " (in-loop)" : "");
    793 #endif
    794 }
    795 
    796 
    797 MaybeObject* KeyedCallIC::LoadFunction(State state,
    798                                        Handle<Object> object,
    799                                        Handle<Object> key) {
    800   if (key->IsSymbol()) {
    801     return CallICBase::LoadFunction(state,
    802                                     Code::kNoExtraICState,
    803                                     object,
    804                                     Handle<String>::cast(key));
    805   }
    806 
    807   if (object->IsUndefined() || object->IsNull()) {
    808     return TypeError("non_object_property_call", object, key);
    809   }
    810 
    811   if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
    812     int argc = target()->arguments_count();
    813     InLoopFlag in_loop = target()->ic_in_loop();
    814     MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
    815         argc, in_loop, Code::KEYED_CALL_IC);
    816     Object* code;
    817     if (maybe_code->ToObject(&code)) {
    818       set_target(Code::cast(code));
    819 #ifdef DEBUG
    820       TraceIC(
    821           "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
    822 #endif
    823     }
    824   }
    825 
    826   HandleScope scope(isolate());
    827   Handle<Object> result = GetProperty(object, key);
    828   RETURN_IF_EMPTY_HANDLE(isolate(), result);
    829 
    830   // Make receiver an object if the callee requires it. Strict mode or builtin
    831   // functions do not wrap the receiver, non-strict functions and objects
    832   // called as functions do.
    833   ReceiverToObjectIfRequired(result, object);
    834 
    835   if (result->IsJSFunction()) return *result;
    836   result = Handle<Object>(TryCallAsFunction(*result));
    837   if (result->IsJSFunction()) return *result;
    838 
    839   return TypeError("property_not_function", object, key);
    840 }
    841 
    842 
    843 #ifdef DEBUG
    844 #define TRACE_IC_NAMED(msg, name) \
    845   if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString())
    846 #else
    847 #define TRACE_IC_NAMED(msg, name)
    848 #endif
    849 
    850 
    851 MaybeObject* LoadIC::Load(State state,
    852                           Handle<Object> object,
    853                           Handle<String> name) {
    854   // If the object is undefined or null it's illegal to try to get any
    855   // of its properties; throw a TypeError in that case.
    856   if (object->IsUndefined() || object->IsNull()) {
    857     return TypeError("non_object_property_load", object, name);
    858   }
    859 
    860   if (FLAG_use_ic) {
    861     Code* non_monomorphic_stub =
    862         (state == UNINITIALIZED) ? pre_monomorphic_stub() : megamorphic_stub();
    863 
    864     // Use specialized code for getting the length of strings and
    865     // string wrapper objects.  The length property of string wrapper
    866     // objects is read-only and therefore always returns the length of
    867     // the underlying string value.  See ECMA-262 15.5.5.1.
    868     if ((object->IsString() || object->IsStringWrapper()) &&
    869         name->Equals(isolate()->heap()->length_symbol())) {
    870       HandleScope scope(isolate());
    871 #ifdef DEBUG
    872       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
    873 #endif
    874       if (state == PREMONOMORPHIC) {
    875         if (object->IsString()) {
    876           Map* map = HeapObject::cast(*object)->map();
    877           const int offset = String::kLengthOffset;
    878           PatchInlinedLoad(address(), map, offset);
    879           set_target(isolate()->builtins()->builtin(
    880               Builtins::kLoadIC_StringLength));
    881         } else {
    882           set_target(isolate()->builtins()->builtin(
    883               Builtins::kLoadIC_StringWrapperLength));
    884         }
    885       } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
    886         set_target(isolate()->builtins()->builtin(
    887             Builtins::kLoadIC_StringWrapperLength));
    888       } else {
    889         set_target(non_monomorphic_stub);
    890       }
    891       // Get the string if we have a string wrapper object.
    892       if (object->IsJSValue()) {
    893         object = Handle<Object>(Handle<JSValue>::cast(object)->value(),
    894                                 isolate());
    895       }
    896       return Smi::FromInt(String::cast(*object)->length());
    897     }
    898 
    899     // Use specialized code for getting the length of arrays.
    900     if (object->IsJSArray() &&
    901         name->Equals(isolate()->heap()->length_symbol())) {
    902 #ifdef DEBUG
    903       if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
    904 #endif
    905       if (state == PREMONOMORPHIC) {
    906         Map* map = HeapObject::cast(*object)->map();
    907         const int offset = JSArray::kLengthOffset;
    908         PatchInlinedLoad(address(), map, offset);
    909         set_target(isolate()->builtins()->builtin(
    910             Builtins::kLoadIC_ArrayLength));
    911       } else {
    912         set_target(non_monomorphic_stub);
    913       }
    914       return JSArray::cast(*object)->length();
    915     }
    916 
    917     // Use specialized code for getting prototype of functions.
    918     if (object->IsJSFunction() &&
    919         name->Equals(isolate()->heap()->prototype_symbol()) &&
    920         JSFunction::cast(*object)->should_have_prototype()) {
    921 #ifdef DEBUG
    922       if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
    923 #endif
    924       if (state == PREMONOMORPHIC) {
    925         set_target(isolate()->builtins()->builtin(
    926             Builtins::kLoadIC_FunctionPrototype));
    927       } else {
    928         set_target(non_monomorphic_stub);
    929       }
    930       return Accessors::FunctionGetPrototype(*object, 0);
    931     }
    932   }
    933 
    934   // Check if the name is trivially convertible to an index and get
    935   // the element if so.
    936   uint32_t index;
    937   if (name->AsArrayIndex(&index)) return object->GetElement(index);
    938 
    939   // Named lookup in the object.
    940   LookupResult lookup;
    941   LookupForRead(*object, *name, &lookup);
    942 
    943   // If we did not find a property, check if we need to throw an exception.
    944   if (!lookup.IsProperty()) {
    945     if (FLAG_strict || IsContextual(object)) {
    946       return ReferenceError("not_defined", name);
    947     }
    948     LOG(isolate(), SuspectReadEvent(*name, *object));
    949   }
    950 
    951   bool can_be_inlined_precheck =
    952       FLAG_use_ic &&
    953       lookup.IsProperty() &&
    954       lookup.IsCacheable() &&
    955       lookup.holder() == *object &&
    956       !object->IsAccessCheckNeeded();
    957 
    958   bool can_be_inlined =
    959       can_be_inlined_precheck &&
    960       state == PREMONOMORPHIC &&
    961       lookup.type() == FIELD;
    962 
    963   bool can_be_inlined_contextual =
    964       can_be_inlined_precheck &&
    965       state == UNINITIALIZED &&
    966       lookup.holder()->IsGlobalObject() &&
    967       lookup.type() == NORMAL;
    968 
    969   if (can_be_inlined) {
    970     Map* map = lookup.holder()->map();
    971     // Property's index in the properties array.  If negative we have
    972     // an inobject property.
    973     int index = lookup.GetFieldIndex() - map->inobject_properties();
    974     if (index < 0) {
    975       // Index is an offset from the end of the object.
    976       int offset = map->instance_size() + (index * kPointerSize);
    977       if (PatchInlinedLoad(address(), map, offset)) {
    978         set_target(megamorphic_stub());
    979         TRACE_IC_NAMED("[LoadIC : inline patch %s]\n", name);
    980         return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
    981       } else {
    982         TRACE_IC_NAMED("[LoadIC : no inline patch %s (patching failed)]\n",
    983                        name);
    984       }
    985     } else {
    986       TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inobject)]\n", name);
    987     }
    988   } else if (can_be_inlined_contextual) {
    989     Map* map = lookup.holder()->map();
    990     JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(
    991         lookup.holder()->property_dictionary()->ValueAt(
    992             lookup.GetDictionaryEntry()));
    993     if (PatchInlinedContextualLoad(address(),
    994                                    map,
    995                                    cell,
    996                                    lookup.IsDontDelete())) {
    997       set_target(megamorphic_stub());
    998       TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name);
    999       ASSERT(cell->value() != isolate()->heap()->the_hole_value());
   1000       return cell->value();
   1001     }
   1002   } else {
   1003     if (FLAG_use_ic && state == PREMONOMORPHIC) {
   1004       TRACE_IC_NAMED("[LoadIC : no inline patch %s (not inlinable)]\n", name);
   1005     }
   1006   }
   1007 
   1008   // Update inline cache and stub cache.
   1009   if (FLAG_use_ic) {
   1010     UpdateCaches(&lookup, state, object, name);
   1011   }
   1012 
   1013   PropertyAttributes attr;
   1014   if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
   1015     // Get the property.
   1016     Object* result;
   1017     { MaybeObject* maybe_result =
   1018           object->GetProperty(*object, &lookup, *name, &attr);
   1019       if (!maybe_result->ToObject(&result)) return maybe_result;
   1020     }
   1021     // If the property is not present, check if we need to throw an
   1022     // exception.
   1023     if (attr == ABSENT && IsContextual(object)) {
   1024       return ReferenceError("not_defined", name);
   1025     }
   1026     return result;
   1027   }
   1028 
   1029   // Get the property.
   1030   return object->GetProperty(*object, &lookup, *name, &attr);
   1031 }
   1032 
   1033 
   1034 void LoadIC::UpdateCaches(LookupResult* lookup,
   1035                           State state,
   1036                           Handle<Object> object,
   1037                           Handle<String> name) {
   1038   // Bail out if the result is not cacheable.
   1039   if (!lookup->IsCacheable()) return;
   1040 
   1041   // Loading properties from values is not common, so don't try to
   1042   // deal with non-JS objects here.
   1043   if (!object->IsJSObject()) return;
   1044   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1045 
   1046   if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
   1047 
   1048   // Compute the code stub for this load.
   1049   MaybeObject* maybe_code = NULL;
   1050   Object* code;
   1051   if (state == UNINITIALIZED) {
   1052     // This is the first time we execute this inline cache.
   1053     // Set the target to the pre monomorphic stub to delay
   1054     // setting the monomorphic state.
   1055     maybe_code = pre_monomorphic_stub();
   1056   } else if (!lookup->IsProperty()) {
   1057     // Nonexistent property. The result is undefined.
   1058     maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name,
   1059                                                                  *receiver);
   1060   } else {
   1061     // Compute monomorphic stub.
   1062     switch (lookup->type()) {
   1063       case FIELD: {
   1064         maybe_code = isolate()->stub_cache()->ComputeLoadField(
   1065             *name,
   1066             *receiver,
   1067             lookup->holder(),
   1068             lookup->GetFieldIndex());
   1069         break;
   1070       }
   1071       case CONSTANT_FUNCTION: {
   1072         Object* constant = lookup->GetConstantFunction();
   1073         maybe_code = isolate()->stub_cache()->ComputeLoadConstant(
   1074             *name, *receiver, lookup->holder(), constant);
   1075         break;
   1076       }
   1077       case NORMAL: {
   1078         if (lookup->holder()->IsGlobalObject()) {
   1079           GlobalObject* global = GlobalObject::cast(lookup->holder());
   1080           JSGlobalPropertyCell* cell =
   1081               JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
   1082           maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
   1083                                                     *receiver,
   1084                                                     global,
   1085                                                     cell,
   1086                                                     lookup->IsDontDelete());
   1087         } else {
   1088           // There is only one shared stub for loading normalized
   1089           // properties. It does not traverse the prototype chain, so the
   1090           // property must be found in the receiver for the stub to be
   1091           // applicable.
   1092           if (lookup->holder() != *receiver) return;
   1093           maybe_code = isolate()->stub_cache()->ComputeLoadNormal();
   1094         }
   1095         break;
   1096       }
   1097       case CALLBACKS: {
   1098         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
   1099         AccessorInfo* callback =
   1100             AccessorInfo::cast(lookup->GetCallbackObject());
   1101         if (v8::ToCData<Address>(callback->getter()) == 0) return;
   1102         maybe_code = isolate()->stub_cache()->ComputeLoadCallback(
   1103             *name, *receiver, lookup->holder(), callback);
   1104         break;
   1105       }
   1106       case INTERCEPTOR: {
   1107         ASSERT(HasInterceptorGetter(lookup->holder()));
   1108         maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor(
   1109             *name, *receiver, lookup->holder());
   1110         break;
   1111       }
   1112       default:
   1113         return;
   1114     }
   1115   }
   1116 
   1117   // If we're unable to compute the stub (not enough memory left), we
   1118   // simply avoid updating the caches.
   1119   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
   1120 
   1121   // Patch the call site depending on the state of the cache.
   1122   if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
   1123       state == MONOMORPHIC_PROTOTYPE_FAILURE) {
   1124     set_target(Code::cast(code));
   1125   } else if (state == MONOMORPHIC) {
   1126     set_target(megamorphic_stub());
   1127   } else if (state == MEGAMORPHIC) {
   1128     // Cache code holding map should be consistent with
   1129     // GenerateMonomorphicCacheProbe.
   1130     Map* map = JSObject::cast(object->IsJSObject() ? *object :
   1131                               object->GetPrototype())->map();
   1132 
   1133     isolate()->stub_cache()->Set(*name, map, Code::cast(code));
   1134   }
   1135 
   1136 #ifdef DEBUG
   1137   TraceIC("LoadIC", name, state, target());
   1138 #endif
   1139 }
   1140 
   1141 
   1142 MaybeObject* KeyedLoadIC::Load(State state,
   1143                                Handle<Object> object,
   1144                                Handle<Object> key) {
   1145   // Check for values that can be converted into a symbol.
   1146   // TODO(1295): Remove this code.
   1147   HandleScope scope(isolate());
   1148   if (key->IsHeapNumber() &&
   1149       isnan(HeapNumber::cast(*key)->value())) {
   1150     key = isolate()->factory()->nan_symbol();
   1151   } else if (key->IsUndefined()) {
   1152     key = isolate()->factory()->undefined_symbol();
   1153   }
   1154 
   1155   if (key->IsSymbol()) {
   1156     Handle<String> name = Handle<String>::cast(key);
   1157 
   1158     // If the object is undefined or null it's illegal to try to get any
   1159     // of its properties; throw a TypeError in that case.
   1160     if (object->IsUndefined() || object->IsNull()) {
   1161       return TypeError("non_object_property_load", object, name);
   1162     }
   1163 
   1164     if (FLAG_use_ic) {
   1165       // TODO(1073): don't ignore the current stub state.
   1166 
   1167       // Use specialized code for getting the length of strings.
   1168       if (object->IsString() &&
   1169           name->Equals(isolate()->heap()->length_symbol())) {
   1170         Handle<String> string = Handle<String>::cast(object);
   1171         Object* code = NULL;
   1172         { MaybeObject* maybe_code =
   1173               isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
   1174                                                                     *string);
   1175           if (!maybe_code->ToObject(&code)) return maybe_code;
   1176         }
   1177         set_target(Code::cast(code));
   1178 #ifdef DEBUG
   1179         TraceIC("KeyedLoadIC", name, state, target());
   1180 #endif  // DEBUG
   1181         return Smi::FromInt(string->length());
   1182       }
   1183 
   1184       // Use specialized code for getting the length of arrays.
   1185       if (object->IsJSArray() &&
   1186           name->Equals(isolate()->heap()->length_symbol())) {
   1187         Handle<JSArray> array = Handle<JSArray>::cast(object);
   1188         Object* code;
   1189         { MaybeObject* maybe_code =
   1190               isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
   1191                                                                    *array);
   1192           if (!maybe_code->ToObject(&code)) return maybe_code;
   1193         }
   1194         set_target(Code::cast(code));
   1195 #ifdef DEBUG
   1196         TraceIC("KeyedLoadIC", name, state, target());
   1197 #endif  // DEBUG
   1198         return JSArray::cast(*object)->length();
   1199       }
   1200 
   1201       // Use specialized code for getting prototype of functions.
   1202       if (object->IsJSFunction() &&
   1203           name->Equals(isolate()->heap()->prototype_symbol()) &&
   1204         JSFunction::cast(*object)->should_have_prototype()) {
   1205         Handle<JSFunction> function = Handle<JSFunction>::cast(object);
   1206         Object* code;
   1207         { MaybeObject* maybe_code =
   1208               isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
   1209                   *name, *function);
   1210           if (!maybe_code->ToObject(&code)) return maybe_code;
   1211         }
   1212         set_target(Code::cast(code));
   1213 #ifdef DEBUG
   1214         TraceIC("KeyedLoadIC", name, state, target());
   1215 #endif  // DEBUG
   1216         return Accessors::FunctionGetPrototype(*object, 0);
   1217       }
   1218     }
   1219 
   1220     // Check if the name is trivially convertible to an index and get
   1221     // the element or char if so.
   1222     uint32_t index = 0;
   1223     if (name->AsArrayIndex(&index)) {
   1224       HandleScope scope(isolate());
   1225       // Rewrite to the generic keyed load stub.
   1226       if (FLAG_use_ic) set_target(generic_stub());
   1227       return Runtime::GetElementOrCharAt(isolate(), object, index);
   1228     }
   1229 
   1230     // Named lookup.
   1231     LookupResult lookup;
   1232     LookupForRead(*object, *name, &lookup);
   1233 
   1234     // If we did not find a property, check if we need to throw an exception.
   1235     if (!lookup.IsProperty()) {
   1236       if (FLAG_strict || IsContextual(object)) {
   1237         return ReferenceError("not_defined", name);
   1238       }
   1239     }
   1240 
   1241     if (FLAG_use_ic) {
   1242       UpdateCaches(&lookup, state, object, name);
   1243     }
   1244 
   1245     PropertyAttributes attr;
   1246     if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
   1247       // Get the property.
   1248       Object* result;
   1249       { MaybeObject* maybe_result =
   1250             object->GetProperty(*object, &lookup, *name, &attr);
   1251         if (!maybe_result->ToObject(&result)) return maybe_result;
   1252       }
   1253       // If the property is not present, check if we need to throw an
   1254       // exception.
   1255       if (attr == ABSENT && IsContextual(object)) {
   1256         return ReferenceError("not_defined", name);
   1257       }
   1258       return result;
   1259     }
   1260 
   1261     return object->GetProperty(*object, &lookup, *name, &attr);
   1262   }
   1263 
   1264   // Do not use ICs for objects that require access checks (including
   1265   // the global object).
   1266   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
   1267 
   1268   if (use_ic) {
   1269     Code* stub = generic_stub();
   1270     if (state == UNINITIALIZED) {
   1271       if (object->IsString() && key->IsNumber()) {
   1272         stub = string_stub();
   1273       } else if (object->IsJSObject()) {
   1274         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1275         if (receiver->HasExternalArrayElements()) {
   1276           MaybeObject* probe =
   1277               isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
   1278                   *receiver, false, kNonStrictMode);
   1279           stub = probe->IsFailure() ?
   1280               NULL : Code::cast(probe->ToObjectUnchecked());
   1281         } else if (receiver->HasIndexedInterceptor()) {
   1282           stub = indexed_interceptor_stub();
   1283         } else if (key->IsSmi() &&
   1284                    receiver->map()->has_fast_elements()) {
   1285           MaybeObject* probe =
   1286               isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver);
   1287           stub = probe->IsFailure() ?
   1288               NULL : Code::cast(probe->ToObjectUnchecked());
   1289         }
   1290       }
   1291     }
   1292     if (stub != NULL) set_target(stub);
   1293 
   1294 #ifdef DEBUG
   1295     TraceIC("KeyedLoadIC", key, state, target());
   1296 #endif  // DEBUG
   1297 
   1298     // For JSObjects with fast elements that are not value wrappers
   1299     // and that do not have indexed interceptors, we initialize the
   1300     // inlined fast case (if present) by patching the inlined map
   1301     // check.
   1302     if (object->IsJSObject() &&
   1303         !object->IsJSValue() &&
   1304         !JSObject::cast(*object)->HasIndexedInterceptor() &&
   1305         JSObject::cast(*object)->HasFastElements()) {
   1306       Map* map = JSObject::cast(*object)->map();
   1307       PatchInlinedLoad(address(), map);
   1308     }
   1309   }
   1310 
   1311   // Get the property.
   1312   return Runtime::GetObjectProperty(isolate(), object, key);
   1313 }
   1314 
   1315 
   1316 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
   1317                                Handle<Object> object, Handle<String> name) {
   1318   // Bail out if we didn't find a result.
   1319   if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
   1320 
   1321   if (!object->IsJSObject()) return;
   1322   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1323 
   1324   if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
   1325 
   1326   // Compute the code stub for this load.
   1327   MaybeObject* maybe_code = NULL;
   1328   Object* code;
   1329 
   1330   if (state == UNINITIALIZED) {
   1331     // This is the first time we execute this inline cache.
   1332     // Set the target to the pre monomorphic stub to delay
   1333     // setting the monomorphic state.
   1334     maybe_code = pre_monomorphic_stub();
   1335   } else {
   1336     // Compute a monomorphic stub.
   1337     switch (lookup->type()) {
   1338       case FIELD: {
   1339         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
   1340             *name, *receiver, lookup->holder(), lookup->GetFieldIndex());
   1341         break;
   1342       }
   1343       case CONSTANT_FUNCTION: {
   1344         Object* constant = lookup->GetConstantFunction();
   1345         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
   1346             *name, *receiver, lookup->holder(), constant);
   1347         break;
   1348       }
   1349       case CALLBACKS: {
   1350         if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
   1351         AccessorInfo* callback =
   1352             AccessorInfo::cast(lookup->GetCallbackObject());
   1353         if (v8::ToCData<Address>(callback->getter()) == 0) return;
   1354         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
   1355             *name, *receiver, lookup->holder(), callback);
   1356         break;
   1357       }
   1358       case INTERCEPTOR: {
   1359         ASSERT(HasInterceptorGetter(lookup->holder()));
   1360         maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
   1361             *name, *receiver, lookup->holder());
   1362         break;
   1363       }
   1364       default: {
   1365         // Always rewrite to the generic case so that we do not
   1366         // repeatedly try to rewrite.
   1367         maybe_code = generic_stub();
   1368         break;
   1369       }
   1370     }
   1371   }
   1372 
   1373   // If we're unable to compute the stub (not enough memory left), we
   1374   // simply avoid updating the caches.
   1375   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
   1376 
   1377   // Patch the call site depending on the state of the cache.  Make
   1378   // sure to always rewrite from monomorphic to megamorphic.
   1379   ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
   1380   if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
   1381     set_target(Code::cast(code));
   1382   } else if (state == MONOMORPHIC) {
   1383     set_target(megamorphic_stub());
   1384   }
   1385 
   1386 #ifdef DEBUG
   1387   TraceIC("KeyedLoadIC", name, state, target());
   1388 #endif
   1389 }
   1390 
   1391 
   1392 static bool StoreICableLookup(LookupResult* lookup) {
   1393   // Bail out if we didn't find a result.
   1394   if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
   1395 
   1396   // If the property is read-only, we leave the IC in its current
   1397   // state.
   1398   if (lookup->IsReadOnly()) return false;
   1399 
   1400   return true;
   1401 }
   1402 
   1403 
   1404 static bool LookupForWrite(JSObject* object,
   1405                            String* name,
   1406                            LookupResult* lookup) {
   1407   object->LocalLookup(name, lookup);
   1408   if (!StoreICableLookup(lookup)) {
   1409     return false;
   1410   }
   1411 
   1412   if (lookup->type() == INTERCEPTOR) {
   1413     if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
   1414       object->LocalLookupRealNamedProperty(name, lookup);
   1415       return StoreICableLookup(lookup);
   1416     }
   1417   }
   1418 
   1419   return true;
   1420 }
   1421 
   1422 
   1423 MaybeObject* StoreIC::Store(State state,
   1424                             StrictModeFlag strict_mode,
   1425                             Handle<Object> object,
   1426                             Handle<String> name,
   1427                             Handle<Object> value) {
   1428   // If the object is undefined or null it's illegal to try to set any
   1429   // properties on it; throw a TypeError in that case.
   1430   if (object->IsUndefined() || object->IsNull()) {
   1431     return TypeError("non_object_property_store", object, name);
   1432   }
   1433 
   1434   if (!object->IsJSObject()) {
   1435     // The length property of string values is read-only. Throw in strict mode.
   1436     if (strict_mode == kStrictMode && object->IsString() &&
   1437         name->Equals(isolate()->heap()->length_symbol())) {
   1438       return TypeError("strict_read_only_property", object, name);
   1439     }
   1440     // Ignore stores where the receiver is not a JSObject.
   1441     return *value;
   1442   }
   1443 
   1444   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1445 
   1446   // Check if the given name is an array index.
   1447   uint32_t index;
   1448   if (name->AsArrayIndex(&index)) {
   1449     HandleScope scope(isolate());
   1450     Handle<Object> result = SetElement(receiver, index, value, strict_mode);
   1451     if (result.is_null()) return Failure::Exception();
   1452     return *value;
   1453   }
   1454 
   1455   // Use specialized code for setting the length of arrays.
   1456   if (receiver->IsJSArray()
   1457       && name->Equals(isolate()->heap()->length_symbol())
   1458       && receiver->AllowsSetElementsLength()) {
   1459 #ifdef DEBUG
   1460     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
   1461 #endif
   1462     Builtins::Name target = (strict_mode == kStrictMode)
   1463         ? Builtins::kStoreIC_ArrayLength_Strict
   1464         : Builtins::kStoreIC_ArrayLength;
   1465     set_target(isolate()->builtins()->builtin(target));
   1466     return receiver->SetProperty(*name, *value, NONE, strict_mode);
   1467   }
   1468 
   1469   // Lookup the property locally in the receiver.
   1470   if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
   1471     LookupResult lookup;
   1472 
   1473     if (LookupForWrite(*receiver, *name, &lookup)) {
   1474       bool can_be_inlined =
   1475           state == UNINITIALIZED &&
   1476           lookup.IsProperty() &&
   1477           lookup.holder() == *receiver &&
   1478           lookup.type() == FIELD &&
   1479           !receiver->IsAccessCheckNeeded();
   1480 
   1481       if (can_be_inlined) {
   1482         Map* map = lookup.holder()->map();
   1483         // Property's index in the properties array.  If negative we have
   1484         // an inobject property.
   1485         int index = lookup.GetFieldIndex() - map->inobject_properties();
   1486         if (index < 0) {
   1487           // Index is an offset from the end of the object.
   1488           int offset = map->instance_size() + (index * kPointerSize);
   1489           if (PatchInlinedStore(address(), map, offset)) {
   1490             set_target((strict_mode == kStrictMode)
   1491                          ? megamorphic_stub_strict()
   1492                          : megamorphic_stub());
   1493 #ifdef DEBUG
   1494             if (FLAG_trace_ic) {
   1495               PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
   1496             }
   1497 #endif
   1498             return receiver->SetProperty(*name, *value, NONE, strict_mode);
   1499 #ifdef DEBUG
   1500 
   1501           } else {
   1502             if (FLAG_trace_ic) {
   1503               PrintF("[StoreIC : no inline patch %s (patching failed)]\n",
   1504                      *name->ToCString());
   1505             }
   1506           }
   1507         } else {
   1508           if (FLAG_trace_ic) {
   1509             PrintF("[StoreIC : no inline patch %s (not inobject)]\n",
   1510                    *name->ToCString());
   1511           }
   1512         }
   1513       } else {
   1514         if (state == PREMONOMORPHIC) {
   1515           if (FLAG_trace_ic) {
   1516             PrintF("[StoreIC : no inline patch %s (not inlinable)]\n",
   1517                    *name->ToCString());
   1518 #endif
   1519           }
   1520         }
   1521       }
   1522 
   1523       // If no inlined store ic was patched, generate a stub for this
   1524       // store.
   1525       UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
   1526     } else {
   1527       // Strict mode doesn't allow setting non-existent global property
   1528       // or an assignment to a read only property.
   1529       if (strict_mode == kStrictMode) {
   1530         if (lookup.IsFound() && lookup.IsReadOnly()) {
   1531           return TypeError("strict_read_only_property", object, name);
   1532         } else if (IsContextual(object)) {
   1533           return ReferenceError("not_defined", name);
   1534         }
   1535       }
   1536     }
   1537   }
   1538 
   1539   if (receiver->IsJSGlobalProxy()) {
   1540     // Generate a generic stub that goes to the runtime when we see a global
   1541     // proxy as receiver.
   1542     Code* stub = (strict_mode == kStrictMode)
   1543         ? global_proxy_stub_strict()
   1544         : global_proxy_stub();
   1545     if (target() != stub) {
   1546       set_target(stub);
   1547 #ifdef DEBUG
   1548       TraceIC("StoreIC", name, state, target());
   1549 #endif
   1550     }
   1551   }
   1552 
   1553   // Set the property.
   1554   return receiver->SetProperty(*name, *value, NONE, strict_mode);
   1555 }
   1556 
   1557 
   1558 void StoreIC::UpdateCaches(LookupResult* lookup,
   1559                            State state,
   1560                            StrictModeFlag strict_mode,
   1561                            Handle<JSObject> receiver,
   1562                            Handle<String> name,
   1563                            Handle<Object> value) {
   1564   // Skip JSGlobalProxy.
   1565   ASSERT(!receiver->IsJSGlobalProxy());
   1566 
   1567   ASSERT(StoreICableLookup(lookup));
   1568 
   1569   // If the property has a non-field type allowing map transitions
   1570   // where there is extra room in the object, we leave the IC in its
   1571   // current state.
   1572   PropertyType type = lookup->type();
   1573 
   1574   // Compute the code stub for this store; used for rewriting to
   1575   // monomorphic state and making sure that the code stub is in the
   1576   // stub cache.
   1577   MaybeObject* maybe_code = NULL;
   1578   Object* code = NULL;
   1579   switch (type) {
   1580     case FIELD: {
   1581       maybe_code = isolate()->stub_cache()->ComputeStoreField(
   1582           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
   1583       break;
   1584     }
   1585     case MAP_TRANSITION: {
   1586       if (lookup->GetAttributes() != NONE) return;
   1587       HandleScope scope(isolate());
   1588       ASSERT(type == MAP_TRANSITION);
   1589       Handle<Map> transition(lookup->GetTransitionMap());
   1590       int index = transition->PropertyIndexFor(*name);
   1591       maybe_code = isolate()->stub_cache()->ComputeStoreField(
   1592           *name, *receiver, index, *transition, strict_mode);
   1593       break;
   1594     }
   1595     case NORMAL: {
   1596       if (receiver->IsGlobalObject()) {
   1597         // The stub generated for the global object picks the value directly
   1598         // from the property cell. So the property must be directly on the
   1599         // global object.
   1600         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
   1601         JSGlobalPropertyCell* cell =
   1602             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
   1603         maybe_code = isolate()->stub_cache()->ComputeStoreGlobal(
   1604             *name, *global, cell, strict_mode);
   1605       } else {
   1606         if (lookup->holder() != *receiver) return;
   1607         maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
   1608       }
   1609       break;
   1610     }
   1611     case CALLBACKS: {
   1612       if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
   1613       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
   1614       if (v8::ToCData<Address>(callback->setter()) == 0) return;
   1615       maybe_code = isolate()->stub_cache()->ComputeStoreCallback(
   1616           *name, *receiver, callback, strict_mode);
   1617       break;
   1618     }
   1619     case INTERCEPTOR: {
   1620       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
   1621       maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor(
   1622           *name, *receiver, strict_mode);
   1623       break;
   1624     }
   1625     default:
   1626       return;
   1627   }
   1628 
   1629   // If we're unable to compute the stub (not enough memory left), we
   1630   // simply avoid updating the caches.
   1631   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
   1632 
   1633   // Patch the call site depending on the state of the cache.
   1634   if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
   1635     set_target(Code::cast(code));
   1636   } else if (state == MONOMORPHIC) {
   1637     // Only move to megamorphic if the target changes.
   1638     if (target() != Code::cast(code)) {
   1639       set_target((strict_mode == kStrictMode)
   1640                    ? megamorphic_stub_strict()
   1641                    : megamorphic_stub());
   1642     }
   1643   } else if (state == MEGAMORPHIC) {
   1644     // Update the stub cache.
   1645     isolate()->stub_cache()->Set(*name,
   1646                                  receiver->map(),
   1647                                  Code::cast(code));
   1648   }
   1649 
   1650 #ifdef DEBUG
   1651   TraceIC("StoreIC", name, state, target());
   1652 #endif
   1653 }
   1654 
   1655 
   1656 MaybeObject* KeyedStoreIC::Store(State state,
   1657                                  StrictModeFlag strict_mode,
   1658                                  Handle<Object> object,
   1659                                  Handle<Object> key,
   1660                                  Handle<Object> value) {
   1661   if (key->IsSymbol()) {
   1662     Handle<String> name = Handle<String>::cast(key);
   1663 
   1664     // If the object is undefined or null it's illegal to try to set any
   1665     // properties on it; throw a TypeError in that case.
   1666     if (object->IsUndefined() || object->IsNull()) {
   1667       return TypeError("non_object_property_store", object, name);
   1668     }
   1669 
   1670     // Ignore stores where the receiver is not a JSObject.
   1671     if (!object->IsJSObject()) return *value;
   1672     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1673 
   1674     // Check if the given name is an array index.
   1675     uint32_t index;
   1676     if (name->AsArrayIndex(&index)) {
   1677       HandleScope scope(isolate());
   1678       Handle<Object> result = SetElement(receiver, index, value, strict_mode);
   1679       if (result.is_null()) return Failure::Exception();
   1680       return *value;
   1681     }
   1682 
   1683     // Lookup the property locally in the receiver.
   1684     LookupResult lookup;
   1685     receiver->LocalLookup(*name, &lookup);
   1686 
   1687     // Update inline cache and stub cache.
   1688     if (FLAG_use_ic) {
   1689       UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
   1690     }
   1691 
   1692     // Set the property.
   1693     return receiver->SetProperty(*name, *value, NONE, strict_mode);
   1694   }
   1695 
   1696   // Do not use ICs for objects that require access checks (including
   1697   // the global object).
   1698   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
   1699   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
   1700 
   1701   if (use_ic) {
   1702     Code* stub =
   1703         (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
   1704     if (state == UNINITIALIZED) {
   1705       if (object->IsJSObject()) {
   1706         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1707         if (receiver->HasExternalArrayElements()) {
   1708           MaybeObject* probe =
   1709               isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
   1710                   *receiver, true, strict_mode);
   1711           stub = probe->IsFailure() ?
   1712               NULL : Code::cast(probe->ToObjectUnchecked());
   1713         } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
   1714           MaybeObject* probe =
   1715               isolate()->stub_cache()->ComputeKeyedStoreSpecialized(
   1716                   *receiver, strict_mode);
   1717           stub = probe->IsFailure() ?
   1718               NULL : Code::cast(probe->ToObjectUnchecked());
   1719         }
   1720       }
   1721     }
   1722     if (stub != NULL) set_target(stub);
   1723   }
   1724 
   1725   // Set the property.
   1726   return Runtime::SetObjectProperty(
   1727       isolate(), object , key, value, NONE, strict_mode);
   1728 }
   1729 
   1730 
   1731 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
   1732                                 State state,
   1733                                 StrictModeFlag strict_mode,
   1734                                 Handle<JSObject> receiver,
   1735                                 Handle<String> name,
   1736                                 Handle<Object> value) {
   1737   // Skip JSGlobalProxy.
   1738   if (receiver->IsJSGlobalProxy()) return;
   1739 
   1740   // Bail out if we didn't find a result.
   1741   if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return;
   1742 
   1743   // If the property is read-only, we leave the IC in its current
   1744   // state.
   1745   if (lookup->IsReadOnly()) return;
   1746 
   1747   // If the property has a non-field type allowing map transitions
   1748   // where there is extra room in the object, we leave the IC in its
   1749   // current state.
   1750   PropertyType type = lookup->type();
   1751 
   1752   // Compute the code stub for this store; used for rewriting to
   1753   // monomorphic state and making sure that the code stub is in the
   1754   // stub cache.
   1755   MaybeObject* maybe_code = NULL;
   1756   Object* code = NULL;
   1757 
   1758   switch (type) {
   1759     case FIELD: {
   1760       maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
   1761           *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
   1762       break;
   1763     }
   1764     case MAP_TRANSITION: {
   1765       if (lookup->GetAttributes() == NONE) {
   1766         HandleScope scope(isolate());
   1767         ASSERT(type == MAP_TRANSITION);
   1768         Handle<Map> transition(lookup->GetTransitionMap());
   1769         int index = transition->PropertyIndexFor(*name);
   1770         maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField(
   1771             *name, *receiver, index, *transition, strict_mode);
   1772         break;
   1773       }
   1774       // fall through.
   1775     }
   1776     default: {
   1777       // Always rewrite to the generic case so that we do not
   1778       // repeatedly try to rewrite.
   1779       maybe_code = (strict_mode == kStrictMode)
   1780           ? generic_stub_strict()
   1781           : generic_stub();
   1782       break;
   1783     }
   1784   }
   1785 
   1786   // If we're unable to compute the stub (not enough memory left), we
   1787   // simply avoid updating the caches.
   1788   if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
   1789 
   1790   // Patch the call site depending on the state of the cache.  Make
   1791   // sure to always rewrite from monomorphic to megamorphic.
   1792   ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
   1793   if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
   1794     set_target(Code::cast(code));
   1795   } else if (state == MONOMORPHIC) {
   1796     set_target((strict_mode == kStrictMode)
   1797                  ? megamorphic_stub_strict()
   1798                  : megamorphic_stub());
   1799   }
   1800 
   1801 #ifdef DEBUG
   1802   TraceIC("KeyedStoreIC", name, state, target());
   1803 #endif
   1804 }
   1805 
   1806 
   1807 // ----------------------------------------------------------------------------
   1808 // Static IC stub generators.
   1809 //
   1810 
   1811 static JSFunction* CompileFunction(Isolate* isolate,
   1812                                    JSFunction* function,
   1813                                    InLoopFlag in_loop) {
   1814   // Compile now with optimization.
   1815   HandleScope scope(isolate);
   1816   Handle<JSFunction> function_handle(function, isolate);
   1817   if (in_loop == IN_LOOP) {
   1818     CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
   1819   } else {
   1820     CompileLazy(function_handle, CLEAR_EXCEPTION);
   1821   }
   1822   return *function_handle;
   1823 }
   1824 
   1825 
   1826 // Used from ic-<arch>.cc.
   1827 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
   1828   NoHandleAllocation na;
   1829   ASSERT(args.length() == 2);
   1830   CallIC ic(isolate);
   1831   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1832   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   1833   MaybeObject* maybe_result = ic.LoadFunction(state,
   1834                                               extra_ic_state,
   1835                                               args.at<Object>(0),
   1836                                               args.at<String>(1));
   1837   Object* result;
   1838   if (!maybe_result->ToObject(&result)) return maybe_result;
   1839 
   1840   // The first time the inline cache is updated may be the first time the
   1841   // function it references gets called.  If the function was lazily compiled
   1842   // then the first call will trigger a compilation.  We check for this case
   1843   // and we do the compilation immediately, instead of waiting for the stub
   1844   // currently attached to the JSFunction object to trigger compilation.  We
   1845   // do this in the case where we know that the inline cache is inside a loop,
   1846   // because then we know that we want to optimize the function.
   1847   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
   1848     return result;
   1849   }
   1850   return CompileFunction(isolate,
   1851                          JSFunction::cast(result),
   1852                          ic.target()->ic_in_loop());
   1853 }
   1854 
   1855 
   1856 // Used from ic-<arch>.cc.
   1857 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
   1858   NoHandleAllocation na;
   1859   ASSERT(args.length() == 2);
   1860   KeyedCallIC ic(isolate);
   1861   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1862   Object* result;
   1863   { MaybeObject* maybe_result =
   1864       ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
   1865     if (!maybe_result->ToObject(&result)) return maybe_result;
   1866   }
   1867 
   1868   if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
   1869     return result;
   1870   }
   1871   return CompileFunction(isolate,
   1872                          JSFunction::cast(result),
   1873                          ic.target()->ic_in_loop());
   1874 }
   1875 
   1876 
   1877 // Used from ic-<arch>.cc.
   1878 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
   1879   NoHandleAllocation na;
   1880   ASSERT(args.length() == 2);
   1881   LoadIC ic(isolate);
   1882   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1883   return ic.Load(state, args.at<Object>(0), args.at<String>(1));
   1884 }
   1885 
   1886 
   1887 // Used from ic-<arch>.cc
   1888 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
   1889   NoHandleAllocation na;
   1890   ASSERT(args.length() == 2);
   1891   KeyedLoadIC ic(isolate);
   1892   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1893   return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
   1894 }
   1895 
   1896 
   1897 // Used from ic-<arch>.cc.
   1898 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
   1899   NoHandleAllocation na;
   1900   ASSERT(args.length() == 3);
   1901   StoreIC ic(isolate);
   1902   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1903   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   1904   return ic.Store(state,
   1905                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
   1906                   args.at<Object>(0),
   1907                   args.at<String>(1),
   1908                   args.at<Object>(2));
   1909 }
   1910 
   1911 
   1912 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
   1913   NoHandleAllocation nha;
   1914 
   1915   ASSERT(args.length() == 2);
   1916   JSObject* receiver = JSObject::cast(args[0]);
   1917   Object* len = args[1];
   1918 
   1919   // The generated code should filter out non-Smis before we get here.
   1920   ASSERT(len->IsSmi());
   1921 
   1922   Object* result;
   1923   { MaybeObject* maybe_result = receiver->SetElementsLength(len);
   1924     if (!maybe_result->ToObject(&result)) return maybe_result;
   1925   }
   1926   return len;
   1927 }
   1928 
   1929 
   1930 // Extend storage is called in a store inline cache when
   1931 // it is necessary to extend the properties array of a
   1932 // JSObject.
   1933 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
   1934   NoHandleAllocation na;
   1935   ASSERT(args.length() == 3);
   1936 
   1937   // Convert the parameters
   1938   JSObject* object = JSObject::cast(args[0]);
   1939   Map* transition = Map::cast(args[1]);
   1940   Object* value = args[2];
   1941 
   1942   // Check the object has run out out property space.
   1943   ASSERT(object->HasFastProperties());
   1944   ASSERT(object->map()->unused_property_fields() == 0);
   1945 
   1946   // Expand the properties array.
   1947   FixedArray* old_storage = object->properties();
   1948   int new_unused = transition->unused_property_fields();
   1949   int new_size = old_storage->length() + new_unused + 1;
   1950   Object* result;
   1951   { MaybeObject* maybe_result = old_storage->CopySize(new_size);
   1952     if (!maybe_result->ToObject(&result)) return maybe_result;
   1953   }
   1954   FixedArray* new_storage = FixedArray::cast(result);
   1955   new_storage->set(old_storage->length(), value);
   1956 
   1957   // Set the new property value and do the map transition.
   1958   object->set_properties(new_storage);
   1959   object->set_map(transition);
   1960 
   1961   // Return the stored value.
   1962   return value;
   1963 }
   1964 
   1965 
   1966 // Used from ic-<arch>.cc.
   1967 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
   1968   NoHandleAllocation na;
   1969   ASSERT(args.length() == 3);
   1970   KeyedStoreIC ic(isolate);
   1971   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   1972   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   1973   return ic.Store(state,
   1974                   static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
   1975                   args.at<Object>(0),
   1976                   args.at<Object>(1),
   1977                   args.at<Object>(2));
   1978 }
   1979 
   1980 
   1981 void TRBinaryOpIC::patch(Code* code) {
   1982   set_target(code);
   1983 }
   1984 
   1985 
   1986 const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
   1987   switch (type_info) {
   1988     case UNINITIALIZED: return "Uninitialized";
   1989     case SMI: return "SMI";
   1990     case INT32: return "Int32s";
   1991     case HEAP_NUMBER: return "HeapNumbers";
   1992     case ODDBALL: return "Oddball";
   1993     case STRING: return "Strings";
   1994     case GENERIC: return "Generic";
   1995     default: return "Invalid";
   1996   }
   1997 }
   1998 
   1999 
   2000 TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) {
   2001   switch (type_info) {
   2002     case UNINITIALIZED:
   2003       return ::v8::internal::UNINITIALIZED;
   2004     case SMI:
   2005     case INT32:
   2006     case HEAP_NUMBER:
   2007     case ODDBALL:
   2008     case STRING:
   2009       return MONOMORPHIC;
   2010     case GENERIC:
   2011       return MEGAMORPHIC;
   2012   }
   2013   UNREACHABLE();
   2014   return ::v8::internal::UNINITIALIZED;
   2015 }
   2016 
   2017 
   2018 TRBinaryOpIC::TypeInfo TRBinaryOpIC::JoinTypes(TRBinaryOpIC::TypeInfo x,
   2019                                                TRBinaryOpIC::TypeInfo y) {
   2020   if (x == UNINITIALIZED) return y;
   2021   if (y == UNINITIALIZED) return x;
   2022   if (x == STRING && y == STRING) return STRING;
   2023   if (x == STRING || y == STRING) return GENERIC;
   2024   if (x >= y) return x;
   2025   return y;
   2026 }
   2027 
   2028 TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left,
   2029                                                  Handle<Object> right) {
   2030   ::v8::internal::TypeInfo left_type =
   2031       ::v8::internal::TypeInfo::TypeFromValue(left);
   2032   ::v8::internal::TypeInfo right_type =
   2033       ::v8::internal::TypeInfo::TypeFromValue(right);
   2034 
   2035   if (left_type.IsSmi() && right_type.IsSmi()) {
   2036     return SMI;
   2037   }
   2038 
   2039   if (left_type.IsInteger32() && right_type.IsInteger32()) {
   2040     // Platforms with 32-bit Smis have no distinct INT32 type.
   2041     if (kSmiValueSize == 32) return SMI;
   2042     return INT32;
   2043   }
   2044 
   2045   if (left_type.IsNumber() && right_type.IsNumber()) {
   2046     return HEAP_NUMBER;
   2047   }
   2048 
   2049   if (left_type.IsString() || right_type.IsString()) {
   2050     // Patching for fast string ADD makes sense even if only one of the
   2051     // arguments is a string.
   2052     return STRING;
   2053   }
   2054 
   2055   // Check for oddball objects.
   2056   if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
   2057   if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
   2058 
   2059   return GENERIC;
   2060 }
   2061 
   2062 
   2063 // defined in code-stubs-<arch>.cc
   2064 // Only needed to remove dependency of ic.cc on code-stubs-<arch>.h.
   2065 Handle<Code> GetTypeRecordingBinaryOpStub(int key,
   2066                                           TRBinaryOpIC::TypeInfo type_info,
   2067                                           TRBinaryOpIC::TypeInfo result_type);
   2068 
   2069 
   2070 RUNTIME_FUNCTION(MaybeObject*, TypeRecordingBinaryOp_Patch) {
   2071   ASSERT(args.length() == 5);
   2072 
   2073   HandleScope scope(isolate);
   2074   Handle<Object> left = args.at<Object>(0);
   2075   Handle<Object> right = args.at<Object>(1);
   2076   int key = Smi::cast(args[2])->value();
   2077   Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
   2078   TRBinaryOpIC::TypeInfo previous_type =
   2079       static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
   2080 
   2081   TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right);
   2082   type = TRBinaryOpIC::JoinTypes(type, previous_type);
   2083   TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED;
   2084   if (type == TRBinaryOpIC::STRING && op != Token::ADD) {
   2085     type = TRBinaryOpIC::GENERIC;
   2086   }
   2087   if (type == TRBinaryOpIC::SMI &&
   2088       previous_type == TRBinaryOpIC::SMI) {
   2089     if (op == Token::DIV || op == Token::MUL || kSmiValueSize == 32) {
   2090       // Arithmetic on two Smi inputs has yielded a heap number.
   2091       // That is the only way to get here from the Smi stub.
   2092       // With 32-bit Smis, all overflows give heap numbers, but with
   2093       // 31-bit Smis, most operations overflow to int32 results.
   2094       result_type = TRBinaryOpIC::HEAP_NUMBER;
   2095     } else {
   2096       // Other operations on SMIs that overflow yield int32s.
   2097       result_type = TRBinaryOpIC::INT32;
   2098     }
   2099   }
   2100   if (type == TRBinaryOpIC::INT32 &&
   2101       previous_type == TRBinaryOpIC::INT32) {
   2102     // We must be here because an operation on two INT32 types overflowed.
   2103     result_type = TRBinaryOpIC::HEAP_NUMBER;
   2104   }
   2105 
   2106   Handle<Code> code = GetTypeRecordingBinaryOpStub(key, type, result_type);
   2107   if (!code.is_null()) {
   2108     if (FLAG_trace_ic) {
   2109       PrintF("[TypeRecordingBinaryOpIC (%s->(%s->%s))#%s]\n",
   2110              TRBinaryOpIC::GetName(previous_type),
   2111              TRBinaryOpIC::GetName(type),
   2112              TRBinaryOpIC::GetName(result_type),
   2113              Token::Name(op));
   2114     }
   2115     TRBinaryOpIC ic(isolate);
   2116     ic.patch(*code);
   2117 
   2118     // Activate inlined smi code.
   2119     if (previous_type == TRBinaryOpIC::UNINITIALIZED) {
   2120       PatchInlinedSmiCode(ic.address());
   2121     }
   2122   }
   2123 
   2124   Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>(
   2125       isolate->thread_local_top()->context_->builtins(), isolate);
   2126   Object* builtin = NULL;  // Initialization calms down the compiler.
   2127   switch (op) {
   2128     case Token::ADD:
   2129       builtin = builtins->javascript_builtin(Builtins::ADD);
   2130       break;
   2131     case Token::SUB:
   2132       builtin = builtins->javascript_builtin(Builtins::SUB);
   2133       break;
   2134     case Token::MUL:
   2135       builtin = builtins->javascript_builtin(Builtins::MUL);
   2136       break;
   2137     case Token::DIV:
   2138       builtin = builtins->javascript_builtin(Builtins::DIV);
   2139       break;
   2140     case Token::MOD:
   2141       builtin = builtins->javascript_builtin(Builtins::MOD);
   2142       break;
   2143     case Token::BIT_AND:
   2144       builtin = builtins->javascript_builtin(Builtins::BIT_AND);
   2145       break;
   2146     case Token::BIT_OR:
   2147       builtin = builtins->javascript_builtin(Builtins::BIT_OR);
   2148       break;
   2149     case Token::BIT_XOR:
   2150       builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
   2151       break;
   2152     case Token::SHR:
   2153       builtin = builtins->javascript_builtin(Builtins::SHR);
   2154       break;
   2155     case Token::SAR:
   2156       builtin = builtins->javascript_builtin(Builtins::SAR);
   2157       break;
   2158     case Token::SHL:
   2159       builtin = builtins->javascript_builtin(Builtins::SHL);
   2160       break;
   2161     default:
   2162       UNREACHABLE();
   2163   }
   2164 
   2165   Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
   2166 
   2167   bool caught_exception;
   2168   Object** builtin_args[] = { right.location() };
   2169   Handle<Object> result = Execution::Call(builtin_function,
   2170                                           left,
   2171                                           ARRAY_SIZE(builtin_args),
   2172                                           builtin_args,
   2173                                           &caught_exception);
   2174   if (caught_exception) {
   2175     return Failure::Exception();
   2176   }
   2177   return *result;
   2178 }
   2179 
   2180 
   2181 Handle<Code> CompareIC::GetUninitialized(Token::Value op) {
   2182   ICCompareStub stub(op, UNINITIALIZED);
   2183   return stub.GetCode();
   2184 }
   2185 
   2186 
   2187 CompareIC::State CompareIC::ComputeState(Code* target) {
   2188   int key = target->major_key();
   2189   if (key == CodeStub::Compare) return GENERIC;
   2190   ASSERT(key == CodeStub::CompareIC);
   2191   return static_cast<State>(target->compare_state());
   2192 }
   2193 
   2194 
   2195 const char* CompareIC::GetStateName(State state) {
   2196   switch (state) {
   2197     case UNINITIALIZED: return "UNINITIALIZED";
   2198     case SMIS: return "SMIS";
   2199     case HEAP_NUMBERS: return "HEAP_NUMBERS";
   2200     case OBJECTS: return "OBJECTS";
   2201     case GENERIC: return "GENERIC";
   2202     default:
   2203       UNREACHABLE();
   2204       return NULL;
   2205   }
   2206 }
   2207 
   2208 
   2209 CompareIC::State CompareIC::TargetState(State state,
   2210                                         bool has_inlined_smi_code,
   2211                                         Handle<Object> x,
   2212                                         Handle<Object> y) {
   2213   if (!has_inlined_smi_code && state != UNINITIALIZED) return GENERIC;
   2214   if (state == UNINITIALIZED && x->IsSmi() && y->IsSmi()) return SMIS;
   2215   if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) &&
   2216       x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
   2217   if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC;
   2218   if (state == UNINITIALIZED &&
   2219       x->IsJSObject() && y->IsJSObject()) return OBJECTS;
   2220   return GENERIC;
   2221 }
   2222 
   2223 
   2224 // Used from ic_<arch>.cc.
   2225 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
   2226   NoHandleAllocation na;
   2227   ASSERT(args.length() == 3);
   2228   CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value()));
   2229   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
   2230   return ic.target();
   2231 }
   2232 
   2233 
   2234 static const Address IC_utilities[] = {
   2235 #define ADDR(name) FUNCTION_ADDR(name),
   2236     IC_UTIL_LIST(ADDR)
   2237     NULL
   2238 #undef ADDR
   2239 };
   2240 
   2241 
   2242 Address IC::AddressFromUtilityId(IC::UtilityId id) {
   2243   return IC_utilities[id];
   2244 }
   2245 
   2246 
   2247 } }  // namespace v8::internal
   2248