Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 char IC::TransitionMarkFromState(IC::State state) {
     44   switch (state) {
     45     case UNINITIALIZED: return '0';
     46     case PREMONOMORPHIC: return '.';
     47     case MONOMORPHIC: return '1';
     48     case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
     49     case POLYMORPHIC: return 'P';
     50     case MEGAMORPHIC: return 'N';
     51     case GENERIC: return 'G';
     52 
     53     // We never see the debugger states here, because the state is
     54     // computed from the original code - not the patched code. Let
     55     // these cases fall through to the unreachable code below.
     56     case DEBUG_STUB: break;
     57   }
     58   UNREACHABLE();
     59   return 0;
     60 }
     61 
     62 
     63 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
     64   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
     65   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
     66     return ".IGNORE_OOB";
     67   }
     68   if (IsGrowStoreMode(mode)) return ".GROW";
     69   return "";
     70 }
     71 
     72 
     73 void IC::TraceIC(const char* type,
     74                  Handle<Object> name,
     75                  State old_state,
     76                  Code* new_target) {
     77   if (FLAG_trace_ic) {
     78     Object* undef = new_target->GetHeap()->undefined_value();
     79     State new_state = StateFrom(new_target, undef, undef);
     80     PrintF("[%s in ", type);
     81     Isolate* isolate = new_target->GetIsolate();
     82     StackFrameIterator it(isolate);
     83     while (it.frame()->fp() != this->fp()) it.Advance();
     84     StackFrame* raw_frame = it.frame();
     85     if (raw_frame->is_internal()) {
     86       Code* apply_builtin = isolate->builtins()->builtin(
     87           Builtins::kFunctionApply);
     88       if (raw_frame->unchecked_code() == apply_builtin) {
     89         PrintF("apply from ");
     90         it.Advance();
     91         raw_frame = it.frame();
     92       }
     93     }
     94     JavaScriptFrame::PrintTop(isolate, stdout, false, true);
     95     Code::ExtraICState state = new_target->extra_ic_state();
     96     const char* modifier =
     97         GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(state));
     98     PrintF(" (%c->%c%s)",
     99            TransitionMarkFromState(old_state),
    100            TransitionMarkFromState(new_state),
    101            modifier);
    102     name->Print();
    103     PrintF("]\n");
    104   }
    105 }
    106 
    107 #define TRACE_GENERIC_IC(isolate, type, reason)                 \
    108   do {                                                          \
    109     if (FLAG_trace_ic) {                                        \
    110       PrintF("[%s patching generic stub in ", type);            \
    111       JavaScriptFrame::PrintTop(isolate, stdout, false, true);  \
    112       PrintF(" (%s)]\n", reason);                               \
    113     }                                                           \
    114   } while (false)
    115 
    116 #else
    117 #define TRACE_GENERIC_IC(isolate, type, reason)
    118 #endif  // DEBUG
    119 
    120 #define TRACE_IC(type, name, old_state, new_target)             \
    121   ASSERT((TraceIC(type, name, old_state, new_target), true))
    122 
    123 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
    124   // To improve the performance of the (much used) IC code, we unfold a few
    125   // levels of the stack frame iteration code. This yields a ~35% speedup when
    126   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
    127   const Address entry =
    128       Isolate::c_entry_fp(isolate->thread_local_top());
    129   Address* pc_address =
    130       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
    131   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
    132   // If there's another JavaScript frame on the stack or a
    133   // StubFailureTrampoline, we need to look one frame further down the stack to
    134   // find the frame pointer and the return address stack slot.
    135   if (depth == EXTRA_CALL_FRAME) {
    136     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
    137     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
    138     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
    139   }
    140 #ifdef DEBUG
    141   StackFrameIterator it(isolate);
    142   for (int i = 0; i < depth + 1; i++) it.Advance();
    143   StackFrame* frame = it.frame();
    144   ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
    145 #endif
    146   fp_ = fp;
    147   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
    148 }
    149 
    150 
    151 #ifdef ENABLE_DEBUGGER_SUPPORT
    152 Address IC::OriginalCodeAddress() const {
    153   HandleScope scope(isolate());
    154   // Compute the JavaScript frame for the frame pointer of this IC
    155   // structure. We need this to be able to find the function
    156   // corresponding to the frame.
    157   StackFrameIterator it(isolate());
    158   while (it.frame()->fp() != this->fp()) it.Advance();
    159   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
    160   // Find the function on the stack and both the active code for the
    161   // function and the original code.
    162   JSFunction* function = frame->function();
    163   Handle<SharedFunctionInfo> shared(function->shared(), isolate());
    164   Code* code = shared->code();
    165   ASSERT(Debug::HasDebugInfo(shared));
    166   Code* original_code = Debug::GetDebugInfo(shared)->original_code();
    167   ASSERT(original_code->IsCode());
    168   // Get the address of the call site in the active code. This is the
    169   // place where the call to DebugBreakXXX is and where the IC
    170   // normally would be.
    171   Address addr = Assembler::target_address_from_return_address(pc());
    172   // Return the address in the original code. This is the place where
    173   // the call which has been overwritten by the DebugBreakXXX resides
    174   // and the place where the inline cache system should look.
    175   intptr_t delta =
    176       original_code->instruction_start() - code->instruction_start();
    177   return addr + delta;
    178 }
    179 #endif
    180 
    181 
    182 static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
    183                                                    Object* receiver,
    184                                                    Object* name) {
    185   if (target->is_keyed_load_stub() ||
    186       target->is_keyed_call_stub() ||
    187       target->is_keyed_store_stub()) {
    188     // Determine whether the failure is due to a name failure.
    189     if (!name->IsName()) return false;
    190     Name* stub_name = target->FindFirstName();
    191     if (Name::cast(name) != stub_name) return false;
    192   }
    193 
    194   InlineCacheHolderFlag cache_holder =
    195       Code::ExtractCacheHolderFromFlags(target->flags());
    196 
    197   Isolate* isolate = target->GetIsolate();
    198   if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
    199     // The stub was generated for JSObject but called for non-JSObject.
    200     // IC::GetCodeCacheHolder is not applicable.
    201     return false;
    202   } else if (cache_holder == PROTOTYPE_MAP &&
    203              receiver->GetPrototype(isolate)->IsNull()) {
    204     // IC::GetCodeCacheHolder is not applicable.
    205     return false;
    206   }
    207   Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map();
    208 
    209   // Decide whether the inline cache failed because of changes to the
    210   // receiver itself or changes to one of its prototypes.
    211   //
    212   // If there are changes to the receiver itself, the map of the
    213   // receiver will have changed and the current target will not be in
    214   // the receiver map's code cache.  Therefore, if the current target
    215   // is in the receiver map's code cache, the inline cache failed due
    216   // to prototype check failure.
    217   int index = map->IndexInCodeCache(name, target);
    218   if (index >= 0) {
    219     map->RemoveFromCodeCache(String::cast(name), target, index);
    220     // For loads and stores, handlers are stored in addition to the ICs on the
    221     // map. Remove those, too.
    222     if ((target->is_load_stub() || target->is_keyed_load_stub() ||
    223          target->is_store_stub() || target->is_keyed_store_stub()) &&
    224         target->type() != Code::NORMAL) {
    225       Code* handler = target->FindFirstCode();
    226       index = map->IndexInCodeCache(name, handler);
    227       if (index >= 0) {
    228         map->RemoveFromCodeCache(String::cast(name), handler, index);
    229       }
    230     }
    231     return true;
    232   }
    233 
    234   // The stub is not in the cache. We've ruled out all other kinds of failure
    235   // except for proptotype chain changes, a deprecated map, a map that's
    236   // different from the one that the stub expects, elements kind changes, or a
    237   // constant global property that will become mutable. Threat all those
    238   // situations as prototype failures (stay monomorphic if possible).
    239 
    240   // If the IC is shared between multiple receivers (slow dictionary mode), then
    241   // the map cannot be deprecated and the stub invalidated.
    242   if (cache_holder == OWN_MAP) {
    243     Map* old_map = target->FindFirstMap();
    244     if (old_map == map) return true;
    245     if (old_map != NULL) {
    246       if (old_map->is_deprecated()) return true;
    247       if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
    248                                               map->elements_kind())) {
    249         return true;
    250       }
    251     }
    252   }
    253 
    254   if (receiver->IsGlobalObject()) {
    255     if (!name->IsName()) return false;
    256     Isolate* isolate = target->GetIsolate();
    257     LookupResult lookup(isolate);
    258     GlobalObject* global = GlobalObject::cast(receiver);
    259     global->LocalLookupRealNamedProperty(Name::cast(name), &lookup);
    260     if (!lookup.IsFound()) return false;
    261     PropertyCell* cell = global->GetPropertyCell(&lookup);
    262     return cell->type()->IsConstant();
    263   }
    264 
    265   return false;
    266 }
    267 
    268 
    269 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
    270   IC::State state = target->ic_state();
    271 
    272   if (state != MONOMORPHIC || !name->IsString()) return state;
    273   if (receiver->IsUndefined() || receiver->IsNull()) return state;
    274 
    275   Code::Kind kind = target->kind();
    276   // Remove the target from the code cache if it became invalid
    277   // because of changes in the prototype chain to avoid hitting it
    278   // again.
    279   // Call stubs handle this later to allow extra IC state
    280   // transitions.
    281   if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC &&
    282       TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
    283     return MONOMORPHIC_PROTOTYPE_FAILURE;
    284   }
    285 
    286   // The builtins object is special.  It only changes when JavaScript
    287   // builtins are loaded lazily.  It is important to keep inline
    288   // caches for the builtins object monomorphic.  Therefore, if we get
    289   // an inline cache miss for the builtins object after lazily loading
    290   // JavaScript builtins, we return uninitialized as the state to
    291   // force the inline cache back to monomorphic state.
    292   if (receiver->IsJSBuiltinsObject()) {
    293     return UNINITIALIZED;
    294   }
    295 
    296   return MONOMORPHIC;
    297 }
    298 
    299 
    300 RelocInfo::Mode IC::ComputeMode() {
    301   Address addr = address();
    302   Code* code = Code::cast(isolate()->FindCodeObject(addr));
    303   for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
    304        !it.done(); it.next()) {
    305     RelocInfo* info = it.rinfo();
    306     if (info->pc() == addr) return info->rmode();
    307   }
    308   UNREACHABLE();
    309   return RelocInfo::NONE32;
    310 }
    311 
    312 
    313 Failure* IC::TypeError(const char* type,
    314                        Handle<Object> object,
    315                        Handle<Object> key) {
    316   HandleScope scope(isolate());
    317   Handle<Object> args[2] = { key, object };
    318   Handle<Object> error = isolate()->factory()->NewTypeError(
    319       type, HandleVector(args, 2));
    320   return isolate()->Throw(*error);
    321 }
    322 
    323 
    324 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
    325   HandleScope scope(isolate());
    326   Handle<Object> error = isolate()->factory()->NewReferenceError(
    327       type, HandleVector(&name, 1));
    328   return isolate()->Throw(*error);
    329 }
    330 
    331 
    332 static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state) {
    333   bool was_uninitialized =
    334       old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
    335   bool is_uninitialized =
    336       new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
    337   return (was_uninitialized && !is_uninitialized) ?  1 :
    338          (!was_uninitialized && is_uninitialized) ? -1 : 0;
    339 }
    340 
    341 
    342 void IC::PostPatching(Address address, Code* target, Code* old_target) {
    343   if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) {
    344     return;
    345   }
    346   Isolate* isolate = target->GetHeap()->isolate();
    347   Code* host = isolate->
    348       inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
    349   if (host->kind() != Code::FUNCTION) return;
    350 
    351   if (FLAG_type_info_threshold > 0 &&
    352       old_target->is_inline_cache_stub() &&
    353       target->is_inline_cache_stub()) {
    354     int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
    355                                           target->ic_state());
    356     // Not all Code objects have TypeFeedbackInfo.
    357     if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
    358       TypeFeedbackInfo* info =
    359           TypeFeedbackInfo::cast(host->type_feedback_info());
    360       info->change_ic_with_type_info_count(delta);
    361     }
    362   }
    363   if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
    364     TypeFeedbackInfo* info =
    365         TypeFeedbackInfo::cast(host->type_feedback_info());
    366     info->change_own_type_change_checksum();
    367   }
    368   if (FLAG_watch_ic_patching) {
    369     host->set_profiler_ticks(0);
    370     isolate->runtime_profiler()->NotifyICChanged();
    371   }
    372   // TODO(2029): When an optimized function is patched, it would
    373   // be nice to propagate the corresponding type information to its
    374   // unoptimized version for the benefit of later inlining.
    375 }
    376 
    377 
    378 void IC::Clear(Address address) {
    379   Code* target = GetTargetAtAddress(address);
    380 
    381   // Don't clear debug break inline cache as it will remove the break point.
    382   if (target->is_debug_stub()) return;
    383 
    384   switch (target->kind()) {
    385     case Code::LOAD_IC: return LoadIC::Clear(address, target);
    386     case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
    387     case Code::STORE_IC: return StoreIC::Clear(address, target);
    388     case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
    389     case Code::CALL_IC: return CallIC::Clear(address, target);
    390     case Code::KEYED_CALL_IC:  return KeyedCallIC::Clear(address, target);
    391     case Code::COMPARE_IC: return CompareIC::Clear(address, target);
    392     case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
    393     case Code::BINARY_OP_IC:
    394     case Code::TO_BOOLEAN_IC:
    395       // Clearing these is tricky and does not
    396       // make any performance difference.
    397       return;
    398     default: UNREACHABLE();
    399   }
    400 }
    401 
    402 
    403 void CallICBase::Clear(Address address, Code* target) {
    404   if (target->ic_state() == UNINITIALIZED) return;
    405   bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
    406   Code* code =
    407       Isolate::Current()->stub_cache()->FindCallInitialize(
    408           target->arguments_count(),
    409           contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
    410           target->kind());
    411   SetTargetAtAddress(address, code);
    412 }
    413 
    414 
    415 void KeyedLoadIC::Clear(Address address, Code* target) {
    416   if (target->ic_state() == UNINITIALIZED) return;
    417   // Make sure to also clear the map used in inline fast cases.  If we
    418   // do not clear these maps, cached code can keep objects alive
    419   // through the embedded maps.
    420   SetTargetAtAddress(address, *initialize_stub());
    421 }
    422 
    423 
    424 void LoadIC::Clear(Address address, Code* target) {
    425   if (target->ic_state() == UNINITIALIZED) return;
    426   SetTargetAtAddress(address, *initialize_stub());
    427 }
    428 
    429 
    430 void StoreIC::Clear(Address address, Code* target) {
    431   if (target->ic_state() == UNINITIALIZED) return;
    432   SetTargetAtAddress(address,
    433       (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
    434         ? *initialize_stub_strict()
    435         : *initialize_stub());
    436 }
    437 
    438 
    439 void KeyedStoreIC::Clear(Address address, Code* target) {
    440   if (target->ic_state() == UNINITIALIZED) return;
    441   SetTargetAtAddress(address,
    442       (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
    443         ? *initialize_stub_strict()
    444         : *initialize_stub());
    445 }
    446 
    447 
    448 void CompareIC::Clear(Address address, Code* target) {
    449   ASSERT(target->major_key() == CodeStub::CompareIC);
    450   CompareIC::State handler_state;
    451   Token::Value op;
    452   ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
    453                                 &handler_state, &op);
    454   // Only clear CompareICs that can retain objects.
    455   if (handler_state != KNOWN_OBJECT) return;
    456   SetTargetAtAddress(address, GetRawUninitialized(op));
    457   PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
    458 }
    459 
    460 
    461 static bool HasInterceptorGetter(JSObject* object) {
    462   return !object->GetNamedInterceptor()->getter()->IsUndefined();
    463 }
    464 
    465 
    466 static void LookupForRead(Handle<Object> object,
    467                           Handle<String> name,
    468                           LookupResult* lookup) {
    469   // Skip all the objects with named interceptors, but
    470   // without actual getter.
    471   while (true) {
    472     object->Lookup(*name, lookup);
    473     // Besides normal conditions (property not found or it's not
    474     // an interceptor), bail out if lookup is not cacheable: we won't
    475     // be able to IC it anyway and regular lookup should work fine.
    476     if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
    477       return;
    478     }
    479 
    480     Handle<JSObject> holder(lookup->holder(), lookup->isolate());
    481     if (HasInterceptorGetter(*holder)) {
    482       return;
    483     }
    484 
    485     holder->LocalLookupRealNamedProperty(*name, lookup);
    486     if (lookup->IsFound()) {
    487       ASSERT(!lookup->IsInterceptor());
    488       return;
    489     }
    490 
    491     Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
    492     if (proto->IsNull()) {
    493       ASSERT(!lookup->IsFound());
    494       return;
    495     }
    496 
    497     object = proto;
    498   }
    499 }
    500 
    501 
    502 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
    503   Handle<Object> delegate = Execution::GetFunctionDelegate(object);
    504 
    505   if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
    506     // Patch the receiver and use the delegate as the function to
    507     // invoke. This is used for invoking objects as if they were functions.
    508     const int argc = target()->arguments_count();
    509     StackFrameLocator locator(isolate());
    510     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    511     int index = frame->ComputeExpressionsCount() - (argc + 1);
    512     frame->SetExpression(index, *object);
    513   }
    514 
    515   return delegate;
    516 }
    517 
    518 
    519 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
    520                                             Handle<Object> object) {
    521   while (callee->IsJSFunctionProxy()) {
    522     callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap(),
    523                             isolate());
    524   }
    525 
    526   if (callee->IsJSFunction()) {
    527     Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
    528     if (!function->shared()->is_classic_mode() || function->IsBuiltin()) {
    529       // Do not wrap receiver for strict mode functions or for builtins.
    530       return;
    531     }
    532   }
    533 
    534   // And only wrap string, number or boolean.
    535   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
    536     // Change the receiver to the result of calling ToObject on it.
    537     const int argc = this->target()->arguments_count();
    538     StackFrameLocator locator(isolate());
    539     JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
    540     int index = frame->ComputeExpressionsCount() - (argc + 1);
    541     frame->SetExpression(index, *isolate()->factory()->ToObject(object));
    542   }
    543 }
    544 
    545 
    546 MaybeObject* CallICBase::LoadFunction(State state,
    547                                       Code::ExtraICState extra_ic_state,
    548                                       Handle<Object> object,
    549                                       Handle<String> name) {
    550   if (object->IsJSObject()) {
    551     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    552     if (receiver->map()->is_deprecated()) {
    553       JSObject::MigrateInstance(receiver);
    554     }
    555   }
    556 
    557   // If the object is undefined or null it's illegal to try to get any
    558   // of its properties; throw a TypeError in that case.
    559   if (object->IsUndefined() || object->IsNull()) {
    560     return TypeError("non_object_property_call", object, name);
    561   }
    562 
    563   // Check if the name is trivially convertible to an index and get
    564   // the element if so.
    565   uint32_t index;
    566   if (name->AsArrayIndex(&index)) {
    567     Handle<Object> result = Object::GetElement(object, index);
    568     RETURN_IF_EMPTY_HANDLE(isolate(), result);
    569     if (result->IsJSFunction()) return *result;
    570 
    571     // Try to find a suitable function delegate for the object at hand.
    572     result = TryCallAsFunction(result);
    573     if (result->IsJSFunction()) return *result;
    574 
    575     // Otherwise, it will fail in the lookup step.
    576   }
    577 
    578   // Lookup the property in the object.
    579   LookupResult lookup(isolate());
    580   LookupForRead(object, name, &lookup);
    581 
    582   if (!lookup.IsFound()) {
    583     // If the object does not have the requested property, check which
    584     // exception we need to throw.
    585     return IsUndeclaredGlobal(object)
    586         ? ReferenceError("not_defined", name)
    587         : TypeError("undefined_method", object, name);
    588   }
    589 
    590   // Lookup is valid: Update inline cache and stub cache.
    591   if (FLAG_use_ic) {
    592     UpdateCaches(&lookup, state, extra_ic_state, object, name);
    593   }
    594 
    595   // Get the property.
    596   PropertyAttributes attr;
    597   Handle<Object> result =
    598       Object::GetProperty(object, object, &lookup, name, &attr);
    599   RETURN_IF_EMPTY_HANDLE(isolate(), result);
    600 
    601   if (lookup.IsInterceptor() && attr == ABSENT) {
    602     // If the object does not have the requested property, check which
    603     // exception we need to throw.
    604     return IsUndeclaredGlobal(object)
    605         ? ReferenceError("not_defined", name)
    606         : TypeError("undefined_method", object, name);
    607   }
    608 
    609   ASSERT(!result->IsTheHole());
    610 
    611   // Make receiver an object if the callee requires it. Strict mode or builtin
    612   // functions do not wrap the receiver, non-strict functions and objects
    613   // called as functions do.
    614   ReceiverToObjectIfRequired(result, object);
    615 
    616   if (result->IsJSFunction()) {
    617     Handle<JSFunction> function = Handle<JSFunction>::cast(result);
    618 #ifdef ENABLE_DEBUGGER_SUPPORT
    619     // Handle stepping into a function if step into is active.
    620     Debug* debug = isolate()->debug();
    621     if (debug->StepInActive()) {
    622       // Protect the result in a handle as the debugger can allocate and might
    623       // cause GC.
    624       debug->HandleStepIn(function, object, fp(), false);
    625     }
    626 #endif
    627     return *function;
    628   }
    629 
    630   // Try to find a suitable function delegate for the object at hand.
    631   result = TryCallAsFunction(result);
    632   if (result->IsJSFunction()) return *result;
    633 
    634   return TypeError("property_not_function", object, name);
    635 }
    636 
    637 
    638 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
    639                                        Handle<Object> object,
    640                                        Code::ExtraICState* extra_ic_state) {
    641   ASSERT(kind_ == Code::CALL_IC);
    642   if (!lookup->IsConstantFunction()) return false;
    643   JSFunction* function = lookup->GetConstantFunction();
    644   if (!function->shared()->HasBuiltinFunctionId()) return false;
    645 
    646   // Fetch the arguments passed to the called function.
    647   const int argc = target()->arguments_count();
    648   Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
    649   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
    650   Arguments args(argc + 1,
    651                  &Memory::Object_at(fp +
    652                                     StandardFrameConstants::kCallerSPOffset +
    653                                     argc * kPointerSize));
    654   switch (function->shared()->builtin_function_id()) {
    655     case kStringCharCodeAt:
    656     case kStringCharAt:
    657       if (object->IsString()) {
    658         String* string = String::cast(*object);
    659         // Check there's the right string value or wrapper in the receiver slot.
    660         ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
    661         // If we're in the default (fastest) state and the index is
    662         // out of bounds, update the state to record this fact.
    663         if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
    664             argc >= 1 && args[1]->IsNumber()) {
    665           double index = DoubleToInteger(args.number_at(1));
    666           if (index < 0 || index >= string->length()) {
    667             *extra_ic_state =
    668                 StringStubState::update(*extra_ic_state,
    669                                         STRING_INDEX_OUT_OF_BOUNDS);
    670             return true;
    671           }
    672         }
    673       }
    674       break;
    675     default:
    676       return false;
    677   }
    678   return false;
    679 }
    680 
    681 
    682 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
    683                                                 State state,
    684                                                 Code::ExtraICState extra_state,
    685                                                 Handle<Object> object,
    686                                                 Handle<String> name) {
    687   int argc = target()->arguments_count();
    688   Handle<JSObject> holder(lookup->holder(), isolate());
    689   switch (lookup->type()) {
    690     case FIELD: {
    691       PropertyIndex index = lookup->GetFieldIndex();
    692       return isolate()->stub_cache()->ComputeCallField(
    693           argc, kind_, extra_state, name, object, holder, index);
    694     }
    695     case CONSTANT: {
    696       if (!lookup->IsConstantFunction()) return Handle<Code>::null();
    697       // Get the constant function and compute the code stub for this
    698       // call; used for rewriting to monomorphic state and making sure
    699       // that the code stub is in the stub cache.
    700       Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
    701       return isolate()->stub_cache()->ComputeCallConstant(
    702           argc, kind_, extra_state, name, object, holder, function);
    703     }
    704     case NORMAL: {
    705       // If we return a null handle, the IC will not be patched.
    706       if (!object->IsJSObject()) return Handle<Code>::null();
    707       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    708 
    709       if (holder->IsGlobalObject()) {
    710         Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
    711         Handle<PropertyCell> cell(
    712             global->GetPropertyCell(lookup), isolate());
    713         if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
    714         Handle<JSFunction> function(JSFunction::cast(cell->value()));
    715         return isolate()->stub_cache()->ComputeCallGlobal(
    716             argc, kind_, extra_state, name, receiver, global, cell, function);
    717       } else {
    718         // There is only one shared stub for calling normalized
    719         // properties. It does not traverse the prototype chain, so the
    720         // property must be found in the receiver for the stub to be
    721         // applicable.
    722         if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
    723         return isolate()->stub_cache()->ComputeCallNormal(
    724             argc, kind_, extra_state);
    725       }
    726       break;
    727     }
    728     case INTERCEPTOR:
    729       ASSERT(HasInterceptorGetter(*holder));
    730       return isolate()->stub_cache()->ComputeCallInterceptor(
    731           argc, kind_, extra_state, name, object, holder);
    732     default:
    733       return Handle<Code>::null();
    734   }
    735 }
    736 
    737 
    738 void CallICBase::UpdateCaches(LookupResult* lookup,
    739                               State state,
    740                               Code::ExtraICState extra_ic_state,
    741                               Handle<Object> object,
    742                               Handle<String> name) {
    743   // Bail out if we didn't find a result.
    744   if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
    745 
    746   // Compute the number of arguments.
    747   int argc = target()->arguments_count();
    748   Handle<Code> code;
    749   if (state == UNINITIALIZED) {
    750     // This is the first time we execute this inline cache.
    751     // Set the target to the pre monomorphic stub to delay
    752     // setting the monomorphic state.
    753     code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
    754         argc, kind_, extra_ic_state);
    755   } else if (state == MONOMORPHIC) {
    756     if (kind_ == Code::CALL_IC &&
    757         TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
    758       code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
    759                                     object, name);
    760     } else if (TryRemoveInvalidPrototypeDependentStub(target(),
    761                                                       *object,
    762                                                       *name)) {
    763       state = MONOMORPHIC_PROTOTYPE_FAILURE;
    764       code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
    765                                     object, name);
    766     } else {
    767       code = isolate()->stub_cache()->ComputeCallMegamorphic(
    768           argc, kind_, extra_ic_state);
    769     }
    770   } else {
    771     code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
    772                                   object, name);
    773   }
    774 
    775   // If there's no appropriate stub we simply avoid updating the caches.
    776   if (code.is_null()) return;
    777 
    778   // Patch the call site depending on the state of the cache.
    779   switch (state) {
    780     case UNINITIALIZED:
    781     case MONOMORPHIC_PROTOTYPE_FAILURE:
    782     case PREMONOMORPHIC:
    783     case MONOMORPHIC:
    784       set_target(*code);
    785       break;
    786     case MEGAMORPHIC: {
    787       // Cache code holding map should be consistent with
    788       // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
    789       Handle<JSObject> cache_object = object->IsJSObject()
    790           ? Handle<JSObject>::cast(object)
    791           : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
    792                              isolate());
    793       // Update the stub cache.
    794       UpdateMegamorphicCache(cache_object->map(), *name, *code);
    795       break;
    796     }
    797     case DEBUG_STUB:
    798       break;
    799     case POLYMORPHIC:
    800     case GENERIC:
    801       UNREACHABLE();
    802       break;
    803   }
    804 
    805   TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
    806            name, state, target());
    807 }
    808 
    809 
    810 MaybeObject* KeyedCallIC::LoadFunction(State state,
    811                                        Handle<Object> object,
    812                                        Handle<Object> key) {
    813   if (key->IsInternalizedString()) {
    814     return CallICBase::LoadFunction(state,
    815                                     Code::kNoExtraICState,
    816                                     object,
    817                                     Handle<String>::cast(key));
    818   }
    819 
    820   if (object->IsJSObject()) {
    821     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    822     if (receiver->map()->is_deprecated()) {
    823       JSObject::MigrateInstance(receiver);
    824     }
    825   }
    826 
    827   if (object->IsUndefined() || object->IsNull()) {
    828     return TypeError("non_object_property_call", object, key);
    829   }
    830 
    831   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
    832   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
    833 
    834   if (use_ic && state != MEGAMORPHIC) {
    835     int argc = target()->arguments_count();
    836     Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic(
    837         argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
    838     if (object->IsJSObject()) {
    839       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    840       if (receiver->elements()->map() ==
    841           isolate()->heap()->non_strict_arguments_elements_map()) {
    842         stub = isolate()->stub_cache()->ComputeCallArguments(argc);
    843       }
    844     }
    845     ASSERT(!stub.is_null());
    846     set_target(*stub);
    847     TRACE_IC("KeyedCallIC", key, state, target());
    848   }
    849 
    850   Handle<Object> result = GetProperty(isolate(), object, key);
    851   RETURN_IF_EMPTY_HANDLE(isolate(), result);
    852 
    853   // Make receiver an object if the callee requires it. Strict mode or builtin
    854   // functions do not wrap the receiver, non-strict functions and objects
    855   // called as functions do.
    856   ReceiverToObjectIfRequired(result, object);
    857   if (result->IsJSFunction()) return *result;
    858 
    859   result = TryCallAsFunction(result);
    860   if (result->IsJSFunction()) return *result;
    861 
    862   return TypeError("property_not_function", object, key);
    863 }
    864 
    865 
    866 MaybeObject* LoadIC::Load(State state,
    867                           Handle<Object> object,
    868                           Handle<String> name) {
    869   // If the object is undefined or null it's illegal to try to get any
    870   // of its properties; throw a TypeError in that case.
    871   if (object->IsUndefined() || object->IsNull()) {
    872     return TypeError("non_object_property_load", object, name);
    873   }
    874 
    875   if (FLAG_use_ic) {
    876     // Use specialized code for getting the length of strings and
    877     // string wrapper objects.  The length property of string wrapper
    878     // objects is read-only and therefore always returns the length of
    879     // the underlying string value.  See ECMA-262 15.5.5.1.
    880     if ((object->IsString() || object->IsStringWrapper()) &&
    881         name->Equals(isolate()->heap()->length_string())) {
    882       Handle<Code> stub;
    883       if (state == UNINITIALIZED) {
    884         stub = pre_monomorphic_stub();
    885       } else if (state == PREMONOMORPHIC) {
    886         StringLengthStub string_length_stub(kind(), !object->IsString());
    887         stub = string_length_stub.GetCode(isolate());
    888       } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
    889         StringLengthStub string_length_stub(kind(), true);
    890         stub = string_length_stub.GetCode(isolate());
    891       } else if (state != MEGAMORPHIC) {
    892         ASSERT(state != GENERIC);
    893         stub = megamorphic_stub();
    894       }
    895       if (!stub.is_null()) {
    896         set_target(*stub);
    897 #ifdef DEBUG
    898         if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
    899 #endif
    900       }
    901       // Get the string if we have a string wrapper object.
    902       Handle<Object> string = object->IsJSValue()
    903           ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate())
    904           : object;
    905       return Smi::FromInt(String::cast(*string)->length());
    906     }
    907 
    908     // Use specialized code for getting prototype of functions.
    909     if (object->IsJSFunction() &&
    910         name->Equals(isolate()->heap()->prototype_string()) &&
    911         Handle<JSFunction>::cast(object)->should_have_prototype()) {
    912       Handle<Code> stub;
    913       if (state == UNINITIALIZED) {
    914         stub = pre_monomorphic_stub();
    915       } else if (state == PREMONOMORPHIC) {
    916         FunctionPrototypeStub function_prototype_stub(kind());
    917         stub = function_prototype_stub.GetCode(isolate());
    918       } else if (state != MEGAMORPHIC) {
    919         ASSERT(state != GENERIC);
    920         stub = megamorphic_stub();
    921       }
    922       if (!stub.is_null()) {
    923         set_target(*stub);
    924 #ifdef DEBUG
    925         if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
    926 #endif
    927       }
    928       return *Accessors::FunctionGetPrototype(object);
    929     }
    930   }
    931 
    932   // Check if the name is trivially convertible to an index and get
    933   // the element or char if so.
    934   uint32_t index;
    935   if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
    936     // Rewrite to the generic keyed load stub.
    937     if (FLAG_use_ic) set_target(*generic_stub());
    938     return Runtime::GetElementOrCharAtOrFail(isolate(), object, index);
    939   }
    940 
    941   if (object->IsJSObject()) {
    942     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    943     if (receiver->map()->is_deprecated()) {
    944       JSObject::MigrateInstance(receiver);
    945     }
    946   }
    947 
    948   // Named lookup in the object.
    949   LookupResult lookup(isolate());
    950   LookupForRead(object, name, &lookup);
    951 
    952   // If we did not find a property, check if we need to throw an exception.
    953   if (!lookup.IsFound()) {
    954     if (IsUndeclaredGlobal(object)) {
    955       return ReferenceError("not_defined", name);
    956     }
    957     LOG(isolate(), SuspectReadEvent(*name, *object));
    958   }
    959 
    960   // Update inline cache and stub cache.
    961   if (FLAG_use_ic) UpdateCaches(&lookup, state, object, name);
    962 
    963   PropertyAttributes attr;
    964   if (lookup.IsInterceptor() || lookup.IsHandler()) {
    965     // Get the property.
    966     Handle<Object> result =
    967         Object::GetProperty(object, object, &lookup, name, &attr);
    968     RETURN_IF_EMPTY_HANDLE(isolate(), result);
    969     // If the property is not present, check if we need to throw an
    970     // exception.
    971     if (attr == ABSENT && IsUndeclaredGlobal(object)) {
    972       return ReferenceError("not_defined", name);
    973     }
    974     return *result;
    975   }
    976 
    977   // Get the property.
    978   return Object::GetPropertyOrFail(object, object, &lookup, name, &attr);
    979 }
    980 
    981 
    982 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
    983                                        Handle<Map> new_receiver_map) {
    984   ASSERT(!new_receiver_map.is_null());
    985   for (int current = 0; current < receiver_maps->length(); ++current) {
    986     if (!receiver_maps->at(current).is_null() &&
    987         receiver_maps->at(current).is_identical_to(new_receiver_map)) {
    988       return false;
    989     }
    990   }
    991   receiver_maps->Add(new_receiver_map);
    992   return true;
    993 }
    994 
    995 
    996 bool IC::UpdatePolymorphicIC(State state,
    997                              Handle<JSObject> receiver,
    998                              Handle<String> name,
    999                              Handle<Code> code,
   1000                              StrictModeFlag strict_mode) {
   1001   if (code->type() == Code::NORMAL) return false;
   1002   if (target()->ic_state() == MONOMORPHIC &&
   1003       target()->type() == Code::NORMAL) {
   1004     return false;
   1005   }
   1006 
   1007   MapHandleList receiver_maps;
   1008   CodeHandleList handlers;
   1009 
   1010   int number_of_valid_maps;
   1011   int handler_to_overwrite = -1;
   1012   Handle<Map> new_receiver_map(receiver->map());
   1013   {
   1014     DisallowHeapAllocation no_gc;
   1015     target()->FindAllMaps(&receiver_maps);
   1016     int number_of_maps = receiver_maps.length();
   1017     number_of_valid_maps = number_of_maps;
   1018 
   1019     for (int i = 0; i < number_of_maps; i++) {
   1020       Handle<Map> map = receiver_maps.at(i);
   1021       // Filter out deprecated maps to ensure its instances get migrated.
   1022       if (map->is_deprecated()) {
   1023         number_of_valid_maps--;
   1024       // If the receiver map is already in the polymorphic IC, this indicates
   1025       // there was a prototoype chain failure. In that case, just overwrite the
   1026       // handler.
   1027       } else if (map.is_identical_to(new_receiver_map)) {
   1028         number_of_valid_maps--;
   1029         handler_to_overwrite = i;
   1030       }
   1031     }
   1032 
   1033     if (number_of_valid_maps >= 4) return false;
   1034 
   1035     // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC.
   1036     // In that case, allow the IC to go back monomorphic.
   1037     if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) {
   1038       return false;
   1039     }
   1040     target()->FindAllCode(&handlers, receiver_maps.length());
   1041   }
   1042 
   1043   number_of_valid_maps++;
   1044   if (handler_to_overwrite >= 0) {
   1045     handlers.Set(handler_to_overwrite, code);
   1046   } else {
   1047     receiver_maps.Add(new_receiver_map);
   1048     handlers.Add(code);
   1049   }
   1050 
   1051   Handle<Code> ic = ComputePolymorphicIC(
   1052       &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode);
   1053   set_target(*ic);
   1054   return true;
   1055 }
   1056 
   1057 
   1058 Handle<Code> LoadIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
   1059                                           CodeHandleList* handlers,
   1060                                           int number_of_valid_maps,
   1061                                           Handle<Name> name,
   1062                                           StrictModeFlag strict_mode) {
   1063   return isolate()->stub_cache()->ComputePolymorphicLoadIC(
   1064       receiver_maps, handlers, number_of_valid_maps, name);
   1065 }
   1066 
   1067 
   1068 Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
   1069                                            CodeHandleList* handlers,
   1070                                            int number_of_valid_maps,
   1071                                            Handle<Name> name,
   1072                                            StrictModeFlag strict_mode) {
   1073   return isolate()->stub_cache()->ComputePolymorphicStoreIC(
   1074       receiver_maps, handlers, number_of_valid_maps, name, strict_mode);
   1075 }
   1076 
   1077 
   1078 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
   1079                                  Handle<Code> handler,
   1080                                  Handle<String> name,
   1081                                  StrictModeFlag strict_mode) {
   1082   if (handler->type() == Code::NORMAL) return set_target(*handler);
   1083   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC(
   1084       receiver, handler, name);
   1085   set_target(*ic);
   1086 }
   1087 
   1088 
   1089 void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
   1090                                       Handle<Code> handler,
   1091                                       Handle<String> name,
   1092                                       StrictModeFlag strict_mode) {
   1093   if (handler->type() == Code::NORMAL) return set_target(*handler);
   1094   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC(
   1095       receiver, handler, name);
   1096   set_target(*ic);
   1097 }
   1098 
   1099 
   1100 void StoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
   1101                                   Handle<Code> handler,
   1102                                   Handle<String> name,
   1103                                   StrictModeFlag strict_mode) {
   1104   if (handler->type() == Code::NORMAL) return set_target(*handler);
   1105   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC(
   1106       receiver, handler, name, strict_mode);
   1107   set_target(*ic);
   1108 }
   1109 
   1110 
   1111 void KeyedStoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
   1112                                        Handle<Code> handler,
   1113                                        Handle<String> name,
   1114                                        StrictModeFlag strict_mode) {
   1115   if (handler->type() == Code::NORMAL) return set_target(*handler);
   1116   Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC(
   1117       receiver, handler, name, strict_mode);
   1118   set_target(*ic);
   1119 }
   1120 
   1121 
   1122 void IC::CopyICToMegamorphicCache(Handle<String> name) {
   1123   MapHandleList receiver_maps;
   1124   CodeHandleList handlers;
   1125   {
   1126     DisallowHeapAllocation no_gc;
   1127     target()->FindAllMaps(&receiver_maps);
   1128     target()->FindAllCode(&handlers, receiver_maps.length());
   1129   }
   1130   for (int i = 0; i < receiver_maps.length(); i++) {
   1131     UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
   1132   }
   1133 }
   1134 
   1135 
   1136 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
   1137   DisallowHeapAllocation no_allocation;
   1138 
   1139   Map* current_map = target()->FindFirstMap();
   1140   ElementsKind receiver_elements_kind = receiver_map->elements_kind();
   1141   bool more_general_transition =
   1142       IsMoreGeneralElementsKindTransition(
   1143         current_map->elements_kind(), receiver_elements_kind);
   1144   Map* transitioned_map = more_general_transition
   1145       ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
   1146       : NULL;
   1147 
   1148   return transitioned_map == receiver_map;
   1149 }
   1150 
   1151 
   1152 // Since GC may have been invoked, by the time PatchCache is called, |state| is
   1153 // not necessarily equal to target()->state().
   1154 void IC::PatchCache(State state,
   1155                     StrictModeFlag strict_mode,
   1156                     Handle<JSObject> receiver,
   1157                     Handle<String> name,
   1158                     Handle<Code> code) {
   1159   switch (state) {
   1160     case UNINITIALIZED:
   1161     case PREMONOMORPHIC:
   1162     case MONOMORPHIC_PROTOTYPE_FAILURE:
   1163       UpdateMonomorphicIC(receiver, code, name, strict_mode);
   1164       break;
   1165     case MONOMORPHIC:
   1166       // Only move to megamorphic if the target changes.
   1167       if (target() != *code) {
   1168         if (target()->is_load_stub() || target()->is_store_stub()) {
   1169           bool is_same_handler = false;
   1170           {
   1171             DisallowHeapAllocation no_allocation;
   1172             Code* old_handler = target()->FindFirstCode();
   1173             is_same_handler = old_handler == *code;
   1174           }
   1175           if (is_same_handler
   1176               && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
   1177             UpdateMonomorphicIC(receiver, code, name, strict_mode);
   1178             break;
   1179           }
   1180           if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
   1181             break;
   1182           }
   1183 
   1184           if (target()->type() != Code::NORMAL) {
   1185             CopyICToMegamorphicCache(name);
   1186           }
   1187         }
   1188 
   1189         UpdateMegamorphicCache(receiver->map(), *name, *code);
   1190         set_target((strict_mode == kStrictMode)
   1191                      ? *megamorphic_stub_strict()
   1192                      : *megamorphic_stub());
   1193       }
   1194       break;
   1195     case MEGAMORPHIC:
   1196       // Update the stub cache.
   1197       UpdateMegamorphicCache(receiver->map(), *name, *code);
   1198       break;
   1199     case POLYMORPHIC:
   1200       if (target()->is_load_stub() || target()->is_store_stub()) {
   1201         if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
   1202           break;
   1203         }
   1204         CopyICToMegamorphicCache(name);
   1205         UpdateMegamorphicCache(receiver->map(), *name, *code);
   1206         set_target((strict_mode == kStrictMode)
   1207                    ? *megamorphic_stub_strict()
   1208                    : *megamorphic_stub());
   1209       } else {
   1210         // When trying to patch a polymorphic keyed load/store element stub
   1211         // with anything other than another polymorphic stub, go generic.
   1212         set_target((strict_mode == kStrictMode)
   1213                    ? *generic_stub_strict()
   1214                    : *generic_stub());
   1215       }
   1216       break;
   1217     case DEBUG_STUB:
   1218       break;
   1219     case GENERIC:
   1220       UNREACHABLE();
   1221       break;
   1222   }
   1223 }
   1224 
   1225 
   1226 static void GetReceiverMapsForStub(Handle<Code> stub,
   1227                                    MapHandleList* result) {
   1228   ASSERT(stub->is_inline_cache_stub());
   1229   switch (stub->ic_state()) {
   1230     case MONOMORPHIC: {
   1231       Map* map = stub->FindFirstMap();
   1232       if (map != NULL) {
   1233         result->Add(Handle<Map>(map));
   1234       }
   1235       break;
   1236     }
   1237     case POLYMORPHIC: {
   1238       DisallowHeapAllocation no_allocation;
   1239       int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   1240       for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
   1241         RelocInfo* info = it.rinfo();
   1242         Handle<Object> object(info->target_object(), stub->GetIsolate());
   1243         if (object->IsString()) break;
   1244         ASSERT(object->IsMap());
   1245         AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
   1246       }
   1247       break;
   1248     }
   1249     case MEGAMORPHIC:
   1250       break;
   1251     case UNINITIALIZED:
   1252     case PREMONOMORPHIC:
   1253     case MONOMORPHIC_PROTOTYPE_FAILURE:
   1254     case GENERIC:
   1255     case DEBUG_STUB:
   1256       UNREACHABLE();
   1257       break;
   1258   }
   1259 }
   1260 
   1261 
   1262 void LoadIC::UpdateCaches(LookupResult* lookup,
   1263                           State state,
   1264                           Handle<Object> object,
   1265                           Handle<String> name) {
   1266   // Bail out if the result is not cacheable.
   1267   if (!lookup->IsCacheable()) {
   1268     set_target(*generic_stub());
   1269     return;
   1270   }
   1271 
   1272   // TODO(jkummerow): It would be nice to support non-JSObjects in
   1273   // UpdateCaches, then we wouldn't need to go generic here.
   1274   if (!object->IsJSObject()) {
   1275     set_target(*generic_stub());
   1276     return;
   1277   }
   1278 
   1279   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1280   Handle<Code> code;
   1281   if (state == UNINITIALIZED) {
   1282     // This is the first time we execute this inline cache.
   1283     // Set the target to the pre monomorphic stub to delay
   1284     // setting the monomorphic state.
   1285     code = pre_monomorphic_stub();
   1286   } else {
   1287     code = ComputeLoadHandler(lookup, receiver, name);
   1288     if (code.is_null()) {
   1289       set_target(*generic_stub());
   1290       return;
   1291     }
   1292   }
   1293 
   1294   PatchCache(state, kNonStrictMode, receiver, name, code);
   1295   TRACE_IC("LoadIC", name, state, target());
   1296 }
   1297 
   1298 
   1299 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
   1300   // Cache code holding map should be consistent with
   1301   // GenerateMonomorphicCacheProbe.
   1302   isolate()->stub_cache()->Set(name, map, code);
   1303 }
   1304 
   1305 
   1306 Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
   1307                                         Handle<JSObject> receiver,
   1308                                         Handle<String> name) {
   1309   if (!lookup->IsProperty()) {
   1310     // Nonexistent property. The result is undefined.
   1311     return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
   1312   }
   1313 
   1314   // Compute monomorphic stub.
   1315   Handle<JSObject> holder(lookup->holder());
   1316   switch (lookup->type()) {
   1317     case FIELD:
   1318       return isolate()->stub_cache()->ComputeLoadField(
   1319           name, receiver, holder,
   1320           lookup->GetFieldIndex(), lookup->representation());
   1321     case CONSTANT: {
   1322       Handle<Object> constant(lookup->GetConstant(), isolate());
   1323       // TODO(2803): Don't compute a stub for cons strings because they cannot
   1324       // be embedded into code.
   1325       if (constant->IsConsString()) return Handle<Code>::null();
   1326       return isolate()->stub_cache()->ComputeLoadConstant(
   1327           name, receiver, holder, constant);
   1328     }
   1329     case NORMAL:
   1330       if (holder->IsGlobalObject()) {
   1331         Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
   1332         Handle<PropertyCell> cell(
   1333             global->GetPropertyCell(lookup), isolate());
   1334         return isolate()->stub_cache()->ComputeLoadGlobal(
   1335             name, receiver, global, cell, lookup->IsDontDelete());
   1336       }
   1337       // There is only one shared stub for loading normalized
   1338       // properties. It does not traverse the prototype chain, so the
   1339       // property must be found in the receiver for the stub to be
   1340       // applicable.
   1341       if (!holder.is_identical_to(receiver)) break;
   1342       return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
   1343     case CALLBACKS: {
   1344       Handle<Object> callback(lookup->GetCallbackObject(), isolate());
   1345       if (callback->IsExecutableAccessorInfo()) {
   1346         Handle<ExecutableAccessorInfo> info =
   1347             Handle<ExecutableAccessorInfo>::cast(callback);
   1348         if (v8::ToCData<Address>(info->getter()) == 0) break;
   1349         if (!info->IsCompatibleReceiver(*receiver)) break;
   1350         return isolate()->stub_cache()->ComputeLoadCallback(
   1351             name, receiver, holder, info);
   1352       } else if (callback->IsAccessorPair()) {
   1353         Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
   1354                               isolate());
   1355         if (!getter->IsJSFunction()) break;
   1356         if (holder->IsGlobalObject()) break;
   1357         if (!holder->HasFastProperties()) break;
   1358         return isolate()->stub_cache()->ComputeLoadViaGetter(
   1359             name, receiver, holder, Handle<JSFunction>::cast(getter));
   1360       } else if (receiver->IsJSArray() &&
   1361           name->Equals(isolate()->heap()->length_string())) {
   1362         PropertyIndex lengthIndex =
   1363           PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
   1364         return isolate()->stub_cache()->ComputeLoadField(
   1365             name, receiver, holder, lengthIndex, Representation::Tagged());
   1366       }
   1367       // TODO(dcarney): Handle correctly.
   1368       if (callback->IsDeclaredAccessorInfo()) break;
   1369       ASSERT(callback->IsForeign());
   1370       // No IC support for old-style native accessors.
   1371       break;
   1372     }
   1373     case INTERCEPTOR:
   1374       ASSERT(HasInterceptorGetter(*holder));
   1375       return isolate()->stub_cache()->ComputeLoadInterceptor(
   1376           name, receiver, holder);
   1377     default:
   1378       break;
   1379   }
   1380   return Handle<Code>::null();
   1381 }
   1382 
   1383 
   1384 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
   1385   // This helper implements a few common fast cases for converting
   1386   // non-smi keys of keyed loads/stores to a smi or a string.
   1387   if (key->IsHeapNumber()) {
   1388     double value = Handle<HeapNumber>::cast(key)->value();
   1389     if (std::isnan(value)) {
   1390       key = isolate->factory()->nan_string();
   1391     } else {
   1392       int int_value = FastD2I(value);
   1393       if (value == int_value && Smi::IsValid(int_value)) {
   1394         key = Handle<Smi>(Smi::FromInt(int_value), isolate);
   1395       }
   1396     }
   1397   } else if (key->IsUndefined()) {
   1398     key = isolate->factory()->undefined_string();
   1399   }
   1400   return key;
   1401 }
   1402 
   1403 
   1404 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
   1405   State ic_state = target()->ic_state();
   1406 
   1407   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
   1408   // via megamorphic stubs, since they don't have a map in their relocation info
   1409   // and so the stubs can't be harvested for the object needed for a map check.
   1410   if (target()->type() != Code::NORMAL) {
   1411     TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
   1412     return generic_stub();
   1413   }
   1414 
   1415   Handle<Map> receiver_map(receiver->map(), isolate());
   1416   MapHandleList target_receiver_maps;
   1417   if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
   1418     // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
   1419     // yet will do so and stay there.
   1420     return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
   1421   }
   1422 
   1423   if (target() == *string_stub()) {
   1424     target_receiver_maps.Add(isolate()->factory()->string_map());
   1425   } else {
   1426     GetReceiverMapsForStub(Handle<Code>(target(), isolate()),
   1427                            &target_receiver_maps);
   1428     if (target_receiver_maps.length() == 0) {
   1429       return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
   1430     }
   1431   }
   1432 
   1433   // The first time a receiver is seen that is a transitioned version of the
   1434   // previous monomorphic receiver type, assume the new ElementsKind is the
   1435   // monomorphic type. This benefits global arrays that only transition
   1436   // once, and all call sites accessing them are faster if they remain
   1437   // monomorphic. If this optimistic assumption is not true, the IC will
   1438   // miss again and it will become polymorphic and support both the
   1439   // untransitioned and transitioned maps.
   1440   if (ic_state == MONOMORPHIC &&
   1441       IsMoreGeneralElementsKindTransition(
   1442           target_receiver_maps.at(0)->elements_kind(),
   1443           receiver->GetElementsKind())) {
   1444     return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
   1445   }
   1446 
   1447   ASSERT(ic_state != GENERIC);
   1448 
   1449   // Determine the list of receiver maps that this call site has seen,
   1450   // adding the map that was just encountered.
   1451   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
   1452     // If the miss wasn't due to an unseen map, a polymorphic stub
   1453     // won't help, use the generic stub.
   1454     TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
   1455     return generic_stub();
   1456   }
   1457 
   1458   // If the maximum number of receiver maps has been exceeded, use the generic
   1459   // version of the IC.
   1460   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
   1461     TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
   1462     return generic_stub();
   1463   }
   1464 
   1465   return isolate()->stub_cache()->ComputeLoadElementPolymorphic(
   1466       &target_receiver_maps);
   1467 }
   1468 
   1469 
   1470 MaybeObject* KeyedLoadIC::Load(State state,
   1471                                Handle<Object> object,
   1472                                Handle<Object> key,
   1473                                ICMissMode miss_mode) {
   1474   // Check for values that can be converted into an internalized string directly
   1475   // or is representable as a smi.
   1476   key = TryConvertKey(key, isolate());
   1477 
   1478   if (key->IsInternalizedString()) {
   1479     return LoadIC::Load(state, object, Handle<String>::cast(key));
   1480   }
   1481 
   1482   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
   1483   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
   1484 
   1485   if (use_ic) {
   1486     Handle<Code> stub = generic_stub();
   1487     if (miss_mode != MISS_FORCE_GENERIC) {
   1488       if (object->IsString() && key->IsNumber()) {
   1489         if (state == UNINITIALIZED) {
   1490           stub = string_stub();
   1491         }
   1492       } else if (object->IsJSObject()) {
   1493         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1494         if (receiver->map()->is_deprecated()) {
   1495           JSObject::MigrateInstance(receiver);
   1496         }
   1497 
   1498         if (receiver->elements()->map() ==
   1499             isolate()->heap()->non_strict_arguments_elements_map()) {
   1500           stub = non_strict_arguments_stub();
   1501         } else if (receiver->HasIndexedInterceptor()) {
   1502           stub = indexed_interceptor_stub();
   1503         } else if (!key->ToSmi()->IsFailure() &&
   1504                    (target() != *non_strict_arguments_stub())) {
   1505           stub = LoadElementStub(receiver);
   1506         }
   1507       }
   1508     } else {
   1509       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic");
   1510     }
   1511     ASSERT(!stub.is_null());
   1512     set_target(*stub);
   1513     TRACE_IC("KeyedLoadIC", key, state, target());
   1514   }
   1515 
   1516 
   1517   return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
   1518 }
   1519 
   1520 
   1521 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
   1522                                              Handle<JSObject> receiver,
   1523                                              Handle<String> name) {
   1524   // Bail out if we didn't find a result.
   1525   if (!lookup->IsProperty()) return Handle<Code>::null();
   1526 
   1527   // Compute a monomorphic stub.
   1528   Handle<JSObject> holder(lookup->holder(), isolate());
   1529   switch (lookup->type()) {
   1530     case FIELD:
   1531       return isolate()->stub_cache()->ComputeKeyedLoadField(
   1532           name, receiver, holder,
   1533           lookup->GetFieldIndex(), lookup->representation());
   1534     case CONSTANT: {
   1535       Handle<Object> constant(lookup->GetConstant(), isolate());
   1536       // TODO(2803): Don't compute a stub for cons strings because they cannot
   1537       // be embedded into code.
   1538       if (constant->IsConsString()) return Handle<Code>::null();
   1539       return isolate()->stub_cache()->ComputeKeyedLoadConstant(
   1540           name, receiver, holder, constant);
   1541     }
   1542     case CALLBACKS: {
   1543       Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
   1544       // TODO(dcarney): Handle DeclaredAccessorInfo correctly.
   1545       if (!callback_object->IsExecutableAccessorInfo()) break;
   1546       Handle<ExecutableAccessorInfo> callback =
   1547           Handle<ExecutableAccessorInfo>::cast(callback_object);
   1548       if (v8::ToCData<Address>(callback->getter()) == 0) break;
   1549       if (!callback->IsCompatibleReceiver(*receiver)) break;
   1550       return isolate()->stub_cache()->ComputeKeyedLoadCallback(
   1551           name, receiver, holder, callback);
   1552     }
   1553     case INTERCEPTOR:
   1554       ASSERT(HasInterceptorGetter(lookup->holder()));
   1555       return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
   1556           name, receiver, holder);
   1557     default:
   1558       // Always rewrite to the generic case so that we do not
   1559       // repeatedly try to rewrite.
   1560       return generic_stub();
   1561   }
   1562   return Handle<Code>::null();
   1563 }
   1564 
   1565 
   1566 static bool LookupForWrite(Handle<JSObject> receiver,
   1567                            Handle<String> name,
   1568                            Handle<Object> value,
   1569                            LookupResult* lookup,
   1570                            IC::State* state) {
   1571   Handle<JSObject> holder = receiver;
   1572   receiver->Lookup(*name, lookup);
   1573   if (lookup->IsFound()) {
   1574     if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
   1575 
   1576     if (lookup->holder() == *receiver) {
   1577       if (lookup->IsInterceptor() &&
   1578           receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
   1579         receiver->LocalLookupRealNamedProperty(*name, lookup);
   1580         return lookup->IsFound() &&
   1581             !lookup->IsReadOnly() &&
   1582             lookup->CanHoldValue(value) &&
   1583             lookup->IsCacheable();
   1584       }
   1585       return lookup->CanHoldValue(value);
   1586     }
   1587 
   1588     if (lookup->IsPropertyCallbacks()) return true;
   1589 
   1590     // Currently normal holders in the prototype chain are not supported. They
   1591     // would require a runtime positive lookup and verification that the details
   1592     // have not changed.
   1593     if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
   1594     holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
   1595   }
   1596 
   1597   // While normally LookupTransition gets passed the receiver, in this case we
   1598   // pass the holder of the property that we overwrite. This keeps the holder in
   1599   // the LookupResult intact so we can later use it to generate a prototype
   1600   // chain check. This avoids a double lookup, but requires us to pass in the
   1601   // receiver when trying to fetch extra information from the transition.
   1602   receiver->map()->LookupTransition(*holder, *name, lookup);
   1603   if (!lookup->IsTransition()) return false;
   1604   PropertyDetails target_details =
   1605       lookup->GetTransitionDetails(receiver->map());
   1606   if (target_details.IsReadOnly()) return false;
   1607 
   1608   // If the value that's being stored does not fit in the field that the
   1609   // instance would transition to, create a new transition that fits the value.
   1610   // This has to be done before generating the IC, since that IC will embed the
   1611   // transition target.
   1612   // Ensure the instance and its map were migrated before trying to update the
   1613   // transition target.
   1614   ASSERT(!receiver->map()->is_deprecated());
   1615   if (!value->FitsRepresentation(target_details.representation())) {
   1616     Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map()));
   1617     Map::GeneralizeRepresentation(
   1618         target, target->LastAdded(), value->OptimalRepresentation());
   1619     // Lookup the transition again since the transition tree may have changed
   1620     // entirely by the migration above.
   1621     receiver->map()->LookupTransition(*holder, *name, lookup);
   1622     if (!lookup->IsTransition()) return false;
   1623     *state = MONOMORPHIC_PROTOTYPE_FAILURE;
   1624   }
   1625   return true;
   1626 }
   1627 
   1628 
   1629 MaybeObject* StoreIC::Store(State state,
   1630                             StrictModeFlag strict_mode,
   1631                             Handle<Object> object,
   1632                             Handle<String> name,
   1633                             Handle<Object> value,
   1634                             JSReceiver::StoreFromKeyed store_mode) {
   1635   // Handle proxies.
   1636   if (object->IsJSProxy()) {
   1637     return JSReceiver::SetPropertyOrFail(
   1638         Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode);
   1639   }
   1640 
   1641   // If the object is undefined or null it's illegal to try to set any
   1642   // properties on it; throw a TypeError in that case.
   1643   if (object->IsUndefined() || object->IsNull()) {
   1644     return TypeError("non_object_property_store", object, name);
   1645   }
   1646 
   1647   // The length property of string values is read-only. Throw in strict mode.
   1648   if (strict_mode == kStrictMode && object->IsString() &&
   1649       name->Equals(isolate()->heap()->length_string())) {
   1650     return TypeError("strict_read_only_property", object, name);
   1651   }
   1652 
   1653   // Ignore other stores where the receiver is not a JSObject.
   1654   // TODO(1475): Must check prototype chains of object wrappers.
   1655   if (!object->IsJSObject()) return *value;
   1656 
   1657   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1658 
   1659   if (receiver->map()->is_deprecated()) {
   1660     JSObject::MigrateInstance(receiver);
   1661   }
   1662 
   1663   // Check if the given name is an array index.
   1664   uint32_t index;
   1665   if (name->AsArrayIndex(&index)) {
   1666     Handle<Object> result =
   1667         JSObject::SetElement(receiver, index, value, NONE, strict_mode);
   1668     RETURN_IF_EMPTY_HANDLE(isolate(), result);
   1669     return *value;
   1670   }
   1671 
   1672   // Observed objects are always modified through the runtime.
   1673   if (FLAG_harmony_observation && receiver->map()->is_observed()) {
   1674     return JSReceiver::SetPropertyOrFail(
   1675         receiver, name, value, NONE, strict_mode, store_mode);
   1676   }
   1677 
   1678   // Use specialized code for setting the length of arrays with fast
   1679   // properties. Slow properties might indicate redefinition of the length
   1680   // property. Note that when redefined using Object.freeze, it's possible
   1681   // to have fast properties but a read-only length.
   1682   if (FLAG_use_ic &&
   1683       receiver->IsJSArray() &&
   1684       name->Equals(isolate()->heap()->length_string()) &&
   1685       Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
   1686       receiver->HasFastProperties() &&
   1687       !receiver->map()->is_frozen()) {
   1688     Handle<Code> stub =
   1689         StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate());
   1690     set_target(*stub);
   1691     TRACE_IC("StoreIC", name, state, *stub);
   1692     return JSReceiver::SetPropertyOrFail(
   1693         receiver, name, value, NONE, strict_mode, store_mode);
   1694   }
   1695 
   1696   if (receiver->IsJSGlobalProxy()) {
   1697     if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
   1698       // Generate a generic stub that goes to the runtime when we see a global
   1699       // proxy as receiver.
   1700       Handle<Code> stub = (strict_mode == kStrictMode)
   1701           ? global_proxy_stub_strict()
   1702           : global_proxy_stub();
   1703       set_target(*stub);
   1704       TRACE_IC("StoreIC", name, state, *stub);
   1705     }
   1706     return JSReceiver::SetPropertyOrFail(
   1707         receiver, name, value, NONE, strict_mode, store_mode);
   1708   }
   1709 
   1710   LookupResult lookup(isolate());
   1711   if (LookupForWrite(receiver, name, value, &lookup, &state)) {
   1712     if (FLAG_use_ic) {
   1713       UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
   1714     }
   1715   } else if (strict_mode == kStrictMode &&
   1716              !(lookup.IsProperty() && lookup.IsReadOnly()) &&
   1717              IsUndeclaredGlobal(object)) {
   1718     // Strict mode doesn't allow setting non-existent global property.
   1719     return ReferenceError("not_defined", name);
   1720   } else if (FLAG_use_ic &&
   1721              (lookup.IsNormal() ||
   1722               (lookup.IsField() && lookup.CanHoldValue(value)))) {
   1723     Handle<Code> stub = strict_mode == kStrictMode
   1724         ? generic_stub_strict() : generic_stub();
   1725     set_target(*stub);
   1726   }
   1727 
   1728   // Set the property.
   1729   return JSReceiver::SetPropertyOrFail(
   1730       receiver, name, value, NONE, strict_mode, store_mode);
   1731 }
   1732 
   1733 
   1734 void StoreIC::UpdateCaches(LookupResult* lookup,
   1735                            State state,
   1736                            StrictModeFlag strict_mode,
   1737                            Handle<JSObject> receiver,
   1738                            Handle<String> name,
   1739                            Handle<Object> value) {
   1740   ASSERT(!receiver->IsJSGlobalProxy());
   1741   ASSERT(lookup->IsFound());
   1742 
   1743   // These are not cacheable, so we never see such LookupResults here.
   1744   ASSERT(!lookup->IsHandler());
   1745 
   1746   Handle<Code> code = ComputeStoreMonomorphic(
   1747       lookup, strict_mode, receiver, name, value);
   1748   if (code.is_null()) {
   1749     Handle<Code> stub = strict_mode == kStrictMode
   1750         ? generic_stub_strict() : generic_stub();
   1751     set_target(*stub);
   1752     return;
   1753   }
   1754 
   1755   PatchCache(state, strict_mode, receiver, name, code);
   1756   TRACE_IC("StoreIC", name, state, target());
   1757 }
   1758 
   1759 
   1760 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
   1761                                               StrictModeFlag strict_mode,
   1762                                               Handle<JSObject> receiver,
   1763                                               Handle<String> name,
   1764                                               Handle<Object> value) {
   1765   Handle<JSObject> holder(lookup->holder());
   1766   switch (lookup->type()) {
   1767     case FIELD:
   1768       return isolate()->stub_cache()->ComputeStoreField(
   1769           name, receiver, lookup, strict_mode);
   1770     case NORMAL:
   1771       if (receiver->IsGlobalObject()) {
   1772         // The stub generated for the global object picks the value directly
   1773         // from the property cell. So the property must be directly on the
   1774         // global object.
   1775         Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
   1776         Handle<PropertyCell> cell(
   1777             global->GetPropertyCell(lookup), isolate());
   1778         return isolate()->stub_cache()->ComputeStoreGlobal(
   1779             name, global, cell, value, strict_mode);
   1780       }
   1781       ASSERT(holder.is_identical_to(receiver));
   1782       return isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
   1783     case CALLBACKS: {
   1784       Handle<Object> callback(lookup->GetCallbackObject(), isolate());
   1785       if (callback->IsExecutableAccessorInfo()) {
   1786         Handle<ExecutableAccessorInfo> info =
   1787             Handle<ExecutableAccessorInfo>::cast(callback);
   1788         if (v8::ToCData<Address>(info->setter()) == 0) break;
   1789         if (!holder->HasFastProperties()) break;
   1790         if (!info->IsCompatibleReceiver(*receiver)) break;
   1791         return isolate()->stub_cache()->ComputeStoreCallback(
   1792             name, receiver, holder, info, strict_mode);
   1793       } else if (callback->IsAccessorPair()) {
   1794         Handle<Object> setter(
   1795             Handle<AccessorPair>::cast(callback)->setter(), isolate());
   1796         if (!setter->IsJSFunction()) break;
   1797         if (holder->IsGlobalObject()) break;
   1798         if (!holder->HasFastProperties()) break;
   1799         return isolate()->stub_cache()->ComputeStoreViaSetter(
   1800             name, receiver, holder, Handle<JSFunction>::cast(setter),
   1801             strict_mode);
   1802       }
   1803       // TODO(dcarney): Handle correctly.
   1804       if (callback->IsDeclaredAccessorInfo()) break;
   1805       ASSERT(callback->IsForeign());
   1806       // No IC support for old-style native accessors.
   1807       break;
   1808     }
   1809     case INTERCEPTOR:
   1810       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
   1811       return isolate()->stub_cache()->ComputeStoreInterceptor(
   1812           name, receiver, strict_mode);
   1813     case CONSTANT:
   1814       break;
   1815     case TRANSITION: {
   1816       // Explicitly pass in the receiver map since LookupForWrite may have
   1817       // stored something else than the receiver in the holder.
   1818       Handle<Map> transition(
   1819           lookup->GetTransitionTarget(receiver->map()), isolate());
   1820       int descriptor = transition->LastAdded();
   1821 
   1822       DescriptorArray* target_descriptors = transition->instance_descriptors();
   1823       PropertyDetails details = target_descriptors->GetDetails(descriptor);
   1824 
   1825       if (details.type() == CALLBACKS || details.attributes() != NONE) break;
   1826 
   1827       return isolate()->stub_cache()->ComputeStoreTransition(
   1828           name, receiver, lookup, transition, strict_mode);
   1829     }
   1830     case NONEXISTENT:
   1831     case HANDLER:
   1832       UNREACHABLE();
   1833       break;
   1834   }
   1835   return Handle<Code>::null();
   1836 }
   1837 
   1838 
   1839 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
   1840                                             KeyedAccessStoreMode store_mode,
   1841                                             StrictModeFlag strict_mode) {
   1842   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
   1843   // via megamorphic stubs, since they don't have a map in their relocation info
   1844   // and so the stubs can't be harvested for the object needed for a map check.
   1845   if (target()->type() != Code::NORMAL) {
   1846     TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
   1847     return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
   1848   }
   1849 
   1850   if (!FLAG_compiled_keyed_stores &&
   1851       (store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
   1852        store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS)) {
   1853     // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support
   1854     // copying COW arrays and silently ignoring some OOB stores into external
   1855     // arrays, but for now use the generic.
   1856     TRACE_GENERIC_IC(isolate(), "KeyedIC", "COW/OOB external array");
   1857     return strict_mode == kStrictMode
   1858         ? generic_stub_strict()
   1859         : generic_stub();
   1860   }
   1861 
   1862   State ic_state = target()->ic_state();
   1863   Handle<Map> receiver_map(receiver->map(), isolate());
   1864   if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
   1865     // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
   1866     // yet will do so and stay there.
   1867     Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
   1868     store_mode = GetNonTransitioningStoreMode(store_mode);
   1869     return isolate()->stub_cache()->ComputeKeyedStoreElement(
   1870         monomorphic_map, strict_mode, store_mode);
   1871   }
   1872 
   1873   MapHandleList target_receiver_maps;
   1874   target()->FindAllMaps(&target_receiver_maps);
   1875   if (target_receiver_maps.length() == 0) {
   1876     // In the case that there is a non-map-specific IC is installed (e.g. keyed
   1877     // stores into properties in dictionary mode), then there will be not
   1878     // receiver maps in the target.
   1879     return strict_mode == kStrictMode
   1880         ? generic_stub_strict()
   1881         : generic_stub();
   1882   }
   1883 
   1884   // There are several special cases where an IC that is MONOMORPHIC can still
   1885   // transition to a different GetNonTransitioningStoreMode IC that handles a
   1886   // superset of the original IC. Handle those here if the receiver map hasn't
   1887   // changed or it has transitioned to a more general kind.
   1888   KeyedAccessStoreMode old_store_mode =
   1889       Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
   1890   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
   1891   if (ic_state == MONOMORPHIC) {
   1892       // If the "old" and "new" maps are in the same elements map family, stay
   1893       // MONOMORPHIC and use the map for the most generic ElementsKind.
   1894     Handle<Map> transitioned_receiver_map = receiver_map;
   1895     if (IsTransitionStoreMode(store_mode)) {
   1896       transitioned_receiver_map =
   1897           ComputeTransitionedMap(receiver, store_mode);
   1898     }
   1899     if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) {
   1900       // Element family is the same, use the "worst" case map.
   1901       store_mode = GetNonTransitioningStoreMode(store_mode);
   1902       return isolate()->stub_cache()->ComputeKeyedStoreElement(
   1903           transitioned_receiver_map, strict_mode, store_mode);
   1904     } else if (*previous_receiver_map == receiver->map() &&
   1905                old_store_mode == STANDARD_STORE &&
   1906                (IsGrowStoreMode(store_mode) ||
   1907                 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1908                 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
   1909       // A "normal" IC that handles stores can switch to a version that can
   1910       // grow at the end of the array, handle OOB accesses or copy COW arrays
   1911       // and still stay MONOMORPHIC.
   1912       return isolate()->stub_cache()->ComputeKeyedStoreElement(
   1913           receiver_map, strict_mode, store_mode);
   1914     }
   1915   }
   1916 
   1917   ASSERT(ic_state != GENERIC);
   1918 
   1919   bool map_added =
   1920       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
   1921 
   1922   if (IsTransitionStoreMode(store_mode)) {
   1923     Handle<Map> transitioned_receiver_map =
   1924         ComputeTransitionedMap(receiver, store_mode);
   1925     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
   1926                                             transitioned_receiver_map);
   1927   }
   1928 
   1929   if (!map_added) {
   1930     // If the miss wasn't due to an unseen map, a polymorphic stub
   1931     // won't help, use the generic stub.
   1932     TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
   1933     return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
   1934   }
   1935 
   1936   // If the maximum number of receiver maps has been exceeded, use the generic
   1937   // version of the IC.
   1938   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
   1939     TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
   1940     return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
   1941   }
   1942 
   1943   // Make sure all polymorphic handlers have the same store mode, otherwise the
   1944   // generic stub must be used.
   1945   store_mode = GetNonTransitioningStoreMode(store_mode);
   1946   if (old_store_mode != STANDARD_STORE) {
   1947     if (store_mode == STANDARD_STORE) {
   1948       store_mode = old_store_mode;
   1949     } else if (store_mode != old_store_mode) {
   1950       TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch");
   1951       return strict_mode == kStrictMode
   1952           ? generic_stub_strict()
   1953           : generic_stub();
   1954     }
   1955   }
   1956 
   1957   // If the store mode isn't the standard mode, make sure that all polymorphic
   1958   // receivers are either external arrays, or all "normal" arrays. Otherwise,
   1959   // use the generic stub.
   1960   if (store_mode != STANDARD_STORE) {
   1961     int external_arrays = 0;
   1962     for (int i = 0; i < target_receiver_maps.length(); ++i) {
   1963       if (target_receiver_maps[i]->has_external_array_elements()) {
   1964         external_arrays++;
   1965       }
   1966     }
   1967     if (external_arrays != 0 &&
   1968         external_arrays != target_receiver_maps.length()) {
   1969       TRACE_GENERIC_IC(isolate(), "KeyedIC",
   1970           "unsupported combination of external and normal arrays");
   1971       return strict_mode == kStrictMode
   1972           ? generic_stub_strict()
   1973           : generic_stub();
   1974     }
   1975   }
   1976 
   1977   return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
   1978       &target_receiver_maps, store_mode, strict_mode);
   1979 }
   1980 
   1981 
   1982 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
   1983     Handle<JSObject> receiver,
   1984     KeyedAccessStoreMode store_mode) {
   1985   switch (store_mode) {
   1986     case STORE_TRANSITION_SMI_TO_OBJECT:
   1987     case STORE_TRANSITION_DOUBLE_TO_OBJECT:
   1988     case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
   1989     case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
   1990       return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
   1991     case STORE_TRANSITION_SMI_TO_DOUBLE:
   1992     case STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
   1993       return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
   1994     case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT:
   1995     case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
   1996     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT:
   1997     case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
   1998       return JSObject::GetElementsTransitionMap(receiver,
   1999                                                 FAST_HOLEY_ELEMENTS);
   2000     case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE:
   2001     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
   2002       return JSObject::GetElementsTransitionMap(receiver,
   2003                                                 FAST_HOLEY_DOUBLE_ELEMENTS);
   2004     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
   2005       ASSERT(receiver->map()->has_external_array_elements());
   2006       // Fall through
   2007     case STORE_NO_TRANSITION_HANDLE_COW:
   2008     case STANDARD_STORE:
   2009     case STORE_AND_GROW_NO_TRANSITION:
   2010       return Handle<Map>(receiver->map(), isolate());
   2011   }
   2012   return Handle<Map>::null();
   2013 }
   2014 
   2015 
   2016 bool IsOutOfBoundsAccess(Handle<JSObject> receiver,
   2017                          int index) {
   2018   if (receiver->IsJSArray()) {
   2019     return JSArray::cast(*receiver)->length()->IsSmi() &&
   2020         index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
   2021   }
   2022   return index >= receiver->elements()->length();
   2023 }
   2024 
   2025 
   2026 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
   2027                                                 Handle<Object> key,
   2028                                                 Handle<Object> value) {
   2029   ASSERT(!key->ToSmi()->IsFailure());
   2030   Smi* smi_key = NULL;
   2031   key->ToSmi()->To(&smi_key);
   2032   int index = smi_key->value();
   2033   bool oob_access = IsOutOfBoundsAccess(receiver, index);
   2034   bool allow_growth = receiver->IsJSArray() && oob_access;
   2035   if (allow_growth) {
   2036     // Handle growing array in stub if necessary.
   2037     if (receiver->HasFastSmiElements()) {
   2038       if (value->IsHeapNumber()) {
   2039         if (receiver->HasFastHoleyElements()) {
   2040           return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE;
   2041         } else {
   2042           return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
   2043         }
   2044       }
   2045       if (value->IsHeapObject()) {
   2046         if (receiver->HasFastHoleyElements()) {
   2047           return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT;
   2048         } else {
   2049           return STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT;
   2050         }
   2051       }
   2052     } else if (receiver->HasFastDoubleElements()) {
   2053       if (!value->IsSmi() && !value->IsHeapNumber()) {
   2054         if (receiver->HasFastHoleyElements()) {
   2055           return STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
   2056         } else {
   2057           return STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT;
   2058         }
   2059       }
   2060     }
   2061     return STORE_AND_GROW_NO_TRANSITION;
   2062   } else {
   2063     // Handle only in-bounds elements accesses.
   2064     if (receiver->HasFastSmiElements()) {
   2065       if (value->IsHeapNumber()) {
   2066         if (receiver->HasFastHoleyElements()) {
   2067           return STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE;
   2068         } else {
   2069           return STORE_TRANSITION_SMI_TO_DOUBLE;
   2070         }
   2071       } else if (value->IsHeapObject()) {
   2072         if (receiver->HasFastHoleyElements()) {
   2073           return STORE_TRANSITION_HOLEY_SMI_TO_OBJECT;
   2074         } else {
   2075           return STORE_TRANSITION_SMI_TO_OBJECT;
   2076         }
   2077       }
   2078     } else if (receiver->HasFastDoubleElements()) {
   2079       if (!value->IsSmi() && !value->IsHeapNumber()) {
   2080         if (receiver->HasFastHoleyElements()) {
   2081           return STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
   2082         } else {
   2083           return STORE_TRANSITION_DOUBLE_TO_OBJECT;
   2084         }
   2085       }
   2086     }
   2087     if (!FLAG_trace_external_array_abuse &&
   2088         receiver->map()->has_external_array_elements() && oob_access) {
   2089       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
   2090     }
   2091     Heap* heap = receiver->GetHeap();
   2092     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
   2093       return STORE_NO_TRANSITION_HANDLE_COW;
   2094     } else {
   2095       return STANDARD_STORE;
   2096     }
   2097   }
   2098 }
   2099 
   2100 
   2101 MaybeObject* KeyedStoreIC::Store(State state,
   2102                                  StrictModeFlag strict_mode,
   2103                                  Handle<Object> object,
   2104                                  Handle<Object> key,
   2105                                  Handle<Object> value,
   2106                                  ICMissMode miss_mode) {
   2107   // Check for values that can be converted into an internalized string directly
   2108   // or is representable as a smi.
   2109   key = TryConvertKey(key, isolate());
   2110 
   2111   if (key->IsInternalizedString()) {
   2112     return StoreIC::Store(state,
   2113                           strict_mode,
   2114                           object,
   2115                           Handle<String>::cast(key),
   2116                           value,
   2117                           JSReceiver::MAY_BE_STORE_FROM_KEYED);
   2118   }
   2119 
   2120   bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
   2121       !(FLAG_harmony_observation && object->IsJSObject() &&
   2122         JSObject::cast(*object)->map()->is_observed());
   2123   if (use_ic && !object->IsSmi()) {
   2124     // Don't use ICs for maps of the objects in Array's prototype chain. We
   2125     // expect to be able to trap element sets to objects with those maps in the
   2126     // runtime to enable optimization of element hole access.
   2127     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
   2128     if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
   2129   }
   2130   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
   2131 
   2132   if (use_ic) {
   2133     Handle<Code> stub = (strict_mode == kStrictMode)
   2134         ? generic_stub_strict()
   2135         : generic_stub();
   2136     if (miss_mode != MISS_FORCE_GENERIC) {
   2137       if (object->IsJSObject()) {
   2138         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   2139         if (receiver->map()->is_deprecated()) {
   2140           JSObject::MigrateInstance(receiver);
   2141         }
   2142         bool key_is_smi_like = key->IsSmi() ||
   2143             (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure());
   2144         if (receiver->elements()->map() ==
   2145             isolate()->heap()->non_strict_arguments_elements_map()) {
   2146           stub = non_strict_arguments_stub();
   2147         } else if (key_is_smi_like &&
   2148                    (target() != *non_strict_arguments_stub())) {
   2149           KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
   2150           stub = StoreElementStub(receiver, store_mode, strict_mode);
   2151         } else {
   2152           TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number");
   2153         }
   2154       } else {
   2155         TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object");
   2156       }
   2157     } else {
   2158       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic");
   2159     }
   2160     ASSERT(!stub.is_null());
   2161     set_target(*stub);
   2162     TRACE_IC("KeyedStoreIC", key, state, target());
   2163   }
   2164 
   2165   return Runtime::SetObjectPropertyOrFail(
   2166       isolate(), object , key, value, NONE, strict_mode);
   2167 }
   2168 
   2169 
   2170 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup,
   2171                                                    StrictModeFlag strict_mode,
   2172                                                    Handle<JSObject> receiver,
   2173                                                    Handle<String> name,
   2174                                                    Handle<Object> value) {
   2175   // If the property has a non-field type allowing map transitions
   2176   // where there is extra room in the object, we leave the IC in its
   2177   // current state.
   2178   switch (lookup->type()) {
   2179     case FIELD:
   2180       return isolate()->stub_cache()->ComputeKeyedStoreField(
   2181           name, receiver, lookup, strict_mode);
   2182     case TRANSITION: {
   2183       // Explicitly pass in the receiver map since LookupForWrite may have
   2184       // stored something else than the receiver in the holder.
   2185       Handle<Map> transition(
   2186           lookup->GetTransitionTarget(receiver->map()), isolate());
   2187       int descriptor = transition->LastAdded();
   2188 
   2189       DescriptorArray* target_descriptors = transition->instance_descriptors();
   2190       PropertyDetails details = target_descriptors->GetDetails(descriptor);
   2191 
   2192       if (details.type() != CALLBACKS && details.attributes() == NONE) {
   2193         return isolate()->stub_cache()->ComputeKeyedStoreTransition(
   2194             name, receiver, lookup, transition, strict_mode);
   2195       }
   2196       // fall through.
   2197     }
   2198     case NORMAL:
   2199     case CONSTANT:
   2200     case CALLBACKS:
   2201     case INTERCEPTOR:
   2202       // Always rewrite to the generic case so that we do not
   2203       // repeatedly try to rewrite.
   2204       return (strict_mode == kStrictMode)
   2205           ? generic_stub_strict()
   2206           : generic_stub();
   2207     case HANDLER:
   2208     case NONEXISTENT:
   2209       UNREACHABLE();
   2210       break;
   2211   }
   2212   return Handle<Code>::null();
   2213 }
   2214 
   2215 
   2216 #undef TRACE_IC
   2217 
   2218 
   2219 // ----------------------------------------------------------------------------
   2220 // Static IC stub generators.
   2221 //
   2222 
   2223 // Used from ic-<arch>.cc.
   2224 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
   2225   HandleScope scope(isolate);
   2226   ASSERT(args.length() == 2);
   2227   CallIC ic(isolate);
   2228   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2229   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2230   MaybeObject* maybe_result = ic.LoadFunction(state,
   2231                                               extra_ic_state,
   2232                                               args.at<Object>(0),
   2233                                               args.at<String>(1));
   2234   JSFunction* raw_function;
   2235   if (!maybe_result->To(&raw_function)) return maybe_result;
   2236 
   2237   // The first time the inline cache is updated may be the first time the
   2238   // function it references gets called. If the function is lazily compiled
   2239   // then the first call will trigger a compilation. We check for this case
   2240   // and we do the compilation immediately, instead of waiting for the stub
   2241   // currently attached to the JSFunction object to trigger compilation.
   2242   if (raw_function->is_compiled()) return raw_function;
   2243 
   2244   Handle<JSFunction> function(raw_function);
   2245   JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
   2246   return *function;
   2247 }
   2248 
   2249 
   2250 // Used from ic-<arch>.cc.
   2251 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
   2252   HandleScope scope(isolate);
   2253   ASSERT(args.length() == 2);
   2254   KeyedCallIC ic(isolate);
   2255   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2256   MaybeObject* maybe_result =
   2257       ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
   2258   // Result could be a function or a failure.
   2259   JSFunction* raw_function = NULL;
   2260   if (!maybe_result->To(&raw_function)) return maybe_result;
   2261 
   2262   if (raw_function->is_compiled()) return raw_function;
   2263 
   2264   Handle<JSFunction> function(raw_function, isolate);
   2265   JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
   2266   return *function;
   2267 }
   2268 
   2269 
   2270 // Used from ic-<arch>.cc.
   2271 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
   2272   HandleScope scope(isolate);
   2273   ASSERT(args.length() == 2);
   2274   LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
   2275   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2276   return ic.Load(state, args.at<Object>(0), args.at<String>(1));
   2277 }
   2278 
   2279 
   2280 // Used from ic-<arch>.cc
   2281 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
   2282   HandleScope scope(isolate);
   2283   ASSERT(args.length() == 2);
   2284   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
   2285   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2286   return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS);
   2287 }
   2288 
   2289 
   2290 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
   2291   HandleScope scope(isolate);
   2292   ASSERT(args.length() == 2);
   2293   KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
   2294   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2295   return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS);
   2296 }
   2297 
   2298 
   2299 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
   2300   HandleScope scope(isolate);
   2301   ASSERT(args.length() == 2);
   2302   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
   2303   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2304   return ic.Load(state,
   2305                  args.at<Object>(0),
   2306                  args.at<Object>(1),
   2307                  MISS_FORCE_GENERIC);
   2308 }
   2309 
   2310 
   2311 // Used from ic-<arch>.cc.
   2312 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
   2313   HandleScope scope(isolate);
   2314   ASSERT(args.length() == 3);
   2315   StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   2316   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2317   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2318   return ic.Store(state,
   2319                   Code::GetStrictMode(extra_ic_state),
   2320                   args.at<Object>(0),
   2321                   args.at<String>(1),
   2322                   args.at<Object>(2));
   2323 }
   2324 
   2325 
   2326 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
   2327   HandleScope scope(isolate);
   2328   ASSERT(args.length() == 3);
   2329   StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
   2330   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2331   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2332   return ic.Store(state,
   2333                   Code::GetStrictMode(extra_ic_state),
   2334                   args.at<Object>(0),
   2335                   args.at<String>(1),
   2336                   args.at<Object>(2));
   2337 }
   2338 
   2339 
   2340 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
   2341   SealHandleScope shs(isolate);
   2342 
   2343   ASSERT(args.length() == 2);
   2344   JSArray* receiver = JSArray::cast(args[0]);
   2345   Object* len = args[1];
   2346 
   2347   // The generated code should filter out non-Smis before we get here.
   2348   ASSERT(len->IsSmi());
   2349 
   2350 #ifdef DEBUG
   2351   // The length property has to be a writable callback property.
   2352   LookupResult debug_lookup(isolate);
   2353   receiver->LocalLookup(isolate->heap()->length_string(), &debug_lookup);
   2354   ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
   2355 #endif
   2356 
   2357   Object* result;
   2358   MaybeObject* maybe_result = receiver->SetElementsLength(len);
   2359   if (!maybe_result->To(&result)) return maybe_result;
   2360 
   2361   return len;
   2362 }
   2363 
   2364 
   2365 // Extend storage is called in a store inline cache when
   2366 // it is necessary to extend the properties array of a
   2367 // JSObject.
   2368 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
   2369   SealHandleScope shs(isolate);
   2370   ASSERT(args.length() == 3);
   2371 
   2372   // Convert the parameters
   2373   JSObject* object = JSObject::cast(args[0]);
   2374   Map* transition = Map::cast(args[1]);
   2375   Object* value = args[2];
   2376 
   2377   // Check the object has run out out property space.
   2378   ASSERT(object->HasFastProperties());
   2379   ASSERT(object->map()->unused_property_fields() == 0);
   2380 
   2381   // Expand the properties array.
   2382   FixedArray* old_storage = object->properties();
   2383   int new_unused = transition->unused_property_fields();
   2384   int new_size = old_storage->length() + new_unused + 1;
   2385   Object* result;
   2386   MaybeObject* maybe_result = old_storage->CopySize(new_size);
   2387   if (!maybe_result->ToObject(&result)) return maybe_result;
   2388 
   2389   FixedArray* new_storage = FixedArray::cast(result);
   2390 
   2391   Object* to_store = value;
   2392 
   2393   if (FLAG_track_double_fields) {
   2394     DescriptorArray* descriptors = transition->instance_descriptors();
   2395     PropertyDetails details = descriptors->GetDetails(transition->LastAdded());
   2396     if (details.representation().IsDouble()) {
   2397       MaybeObject* maybe_storage =
   2398           isolate->heap()->AllocateHeapNumber(value->Number());
   2399       if (!maybe_storage->To(&to_store)) return maybe_storage;
   2400     }
   2401   }
   2402 
   2403   new_storage->set(old_storage->length(), to_store);
   2404 
   2405   // Set the new property value and do the map transition.
   2406   object->set_properties(new_storage);
   2407   object->set_map(transition);
   2408 
   2409   // Return the stored value.
   2410   return value;
   2411 }
   2412 
   2413 
   2414 // Used from ic-<arch>.cc.
   2415 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
   2416   HandleScope scope(isolate);
   2417   ASSERT(args.length() == 3);
   2418   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   2419   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2420   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2421   return ic.Store(state,
   2422                   Code::GetStrictMode(extra_ic_state),
   2423                   args.at<Object>(0),
   2424                   args.at<Object>(1),
   2425                   args.at<Object>(2),
   2426                   MISS);
   2427 }
   2428 
   2429 
   2430 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
   2431   HandleScope scope(isolate);
   2432   ASSERT(args.length() == 3);
   2433   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
   2434   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2435   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2436   return ic.Store(state,
   2437                   Code::GetStrictMode(extra_ic_state),
   2438                   args.at<Object>(0),
   2439                   args.at<Object>(1),
   2440                   args.at<Object>(2),
   2441                   MISS);
   2442 }
   2443 
   2444 
   2445 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
   2446   SealHandleScope shs(isolate);
   2447   ASSERT(args.length() == 3);
   2448   StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   2449   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2450   Handle<Object> object = args.at<Object>(0);
   2451   Handle<Object> key = args.at<Object>(1);
   2452   Handle<Object> value = args.at<Object>(2);
   2453   StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
   2454   return Runtime::SetObjectProperty(isolate,
   2455                                     object,
   2456                                     key,
   2457                                     value,
   2458                                     NONE,
   2459                                     strict_mode);
   2460 }
   2461 
   2462 
   2463 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
   2464   SealHandleScope shs(isolate);
   2465   ASSERT(args.length() == 3);
   2466   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   2467   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2468   Handle<Object> object = args.at<Object>(0);
   2469   Handle<Object> key = args.at<Object>(1);
   2470   Handle<Object> value = args.at<Object>(2);
   2471   StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
   2472   return Runtime::SetObjectProperty(isolate,
   2473                                     object,
   2474                                     key,
   2475                                     value,
   2476                                     NONE,
   2477                                     strict_mode);
   2478 }
   2479 
   2480 
   2481 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
   2482   HandleScope scope(isolate);
   2483   ASSERT(args.length() == 3);
   2484   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
   2485   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   2486   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2487   return ic.Store(state,
   2488                   Code::GetStrictMode(extra_ic_state),
   2489                   args.at<Object>(0),
   2490                   args.at<Object>(1),
   2491                   args.at<Object>(2),
   2492                   MISS_FORCE_GENERIC);
   2493 }
   2494 
   2495 
   2496 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
   2497   SealHandleScope scope(isolate);
   2498   ASSERT(args.length() == 4);
   2499   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
   2500   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
   2501   Handle<Object> value = args.at<Object>(0);
   2502   Handle<Object> key = args.at<Object>(2);
   2503   Handle<Object> object = args.at<Object>(3);
   2504   StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
   2505   return Runtime::SetObjectProperty(isolate,
   2506                                     object,
   2507                                     key,
   2508                                     value,
   2509                                     NONE,
   2510                                     strict_mode);
   2511 }
   2512 
   2513 
   2514 void BinaryOpIC::patch(Code* code) {
   2515   set_target(code);
   2516 }
   2517 
   2518 
   2519 const char* BinaryOpIC::GetName(TypeInfo type_info) {
   2520   switch (type_info) {
   2521     case UNINITIALIZED: return "Uninitialized";
   2522     case SMI: return "Smi";
   2523     case INT32: return "Int32";
   2524     case NUMBER: return "Number";
   2525     case ODDBALL: return "Oddball";
   2526     case STRING: return "String";
   2527     case GENERIC: return "Generic";
   2528     default: return "Invalid";
   2529   }
   2530 }
   2531 
   2532 
   2533 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
   2534   switch (type_info) {
   2535     case UNINITIALIZED:
   2536       return ::v8::internal::UNINITIALIZED;
   2537     case SMI:
   2538     case INT32:
   2539     case NUMBER:
   2540     case ODDBALL:
   2541     case STRING:
   2542       return MONOMORPHIC;
   2543     case GENERIC:
   2544       return ::v8::internal::GENERIC;
   2545   }
   2546   UNREACHABLE();
   2547   return ::v8::internal::UNINITIALIZED;
   2548 }
   2549 
   2550 
   2551 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type,
   2552                                         Isolate* isolate) {
   2553   switch (binary_type) {
   2554     case UNINITIALIZED:
   2555       return handle(Type::None(), isolate);
   2556     case SMI:
   2557       return handle(Type::Smi(), isolate);
   2558     case INT32:
   2559       return handle(Type::Signed32(), isolate);
   2560     case NUMBER:
   2561       return handle(Type::Number(), isolate);
   2562     case ODDBALL:
   2563       return handle(Type::Optional(
   2564           handle(Type::Union(
   2565               handle(Type::Number(), isolate),
   2566               handle(Type::String(), isolate)), isolate)), isolate);
   2567     case STRING:
   2568       return handle(Type::String(), isolate);
   2569     case GENERIC:
   2570       return handle(Type::Any(), isolate);
   2571   }
   2572   UNREACHABLE();
   2573   return handle(Type::Any(), isolate);
   2574 }
   2575 
   2576 
   2577 void BinaryOpIC::StubInfoToType(int minor_key,
   2578                                 Handle<Type>* left,
   2579                                 Handle<Type>* right,
   2580                                 Handle<Type>* result,
   2581                                 Isolate* isolate) {
   2582   TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
   2583   BinaryOpStub::decode_types_from_minor_key(
   2584       minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
   2585   *left = TypeInfoToType(left_typeinfo, isolate);
   2586   *right = TypeInfoToType(right_typeinfo, isolate);
   2587   *result = TypeInfoToType(result_typeinfo, isolate);
   2588 }
   2589 
   2590 
   2591 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
   2592                                               Token::Value op) {
   2593   v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
   2594   if (type.IsSmi()) return BinaryOpIC::SMI;
   2595   if (type.IsInteger32()) {
   2596     if (kSmiValueSize == 32) return BinaryOpIC::SMI;
   2597     return BinaryOpIC::INT32;
   2598   }
   2599   if (type.IsNumber()) return BinaryOpIC::NUMBER;
   2600   if (type.IsString()) return BinaryOpIC::STRING;
   2601   if (value->IsUndefined()) {
   2602     if (op == Token::BIT_AND ||
   2603         op == Token::BIT_OR ||
   2604         op == Token::BIT_XOR ||
   2605         op == Token::SAR ||
   2606         op == Token::SHL ||
   2607         op == Token::SHR) {
   2608       if (kSmiValueSize == 32) return BinaryOpIC::SMI;
   2609       return BinaryOpIC::INT32;
   2610     }
   2611     return BinaryOpIC::ODDBALL;
   2612   }
   2613   return BinaryOpIC::GENERIC;
   2614 }
   2615 
   2616 
   2617 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type,
   2618                                        Handle<Object> value,
   2619                                        Token::Value op) {
   2620   BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op);
   2621   if (old_type == BinaryOpIC::STRING) {
   2622     if (new_type == BinaryOpIC::STRING) return new_type;
   2623     return BinaryOpIC::GENERIC;
   2624   }
   2625   return Max(old_type, new_type);
   2626 }
   2627 
   2628 
   2629 #ifdef DEBUG
   2630 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
   2631                           BinaryOpIC::TypeInfo right,
   2632                           Maybe<int32_t> fixed_right_arg,
   2633                           BinaryOpIC::TypeInfo result) {
   2634   PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
   2635   if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
   2636   PrintF("->%s", BinaryOpIC::GetName(result));
   2637 }
   2638 #endif
   2639 
   2640 
   2641 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
   2642   ASSERT(args.length() == 3);
   2643 
   2644   HandleScope scope(isolate);
   2645   Handle<Object> left = args.at<Object>(0);
   2646   Handle<Object> right = args.at<Object>(1);
   2647   int key = args.smi_at(2);
   2648   Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
   2649 
   2650   BinaryOpIC::TypeInfo previous_left, previous_right, previous_result;
   2651   BinaryOpStub::decode_types_from_minor_key(
   2652       key, &previous_left, &previous_right, &previous_result);
   2653 
   2654   BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
   2655   BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
   2656   BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
   2657 
   2658   // STRING is only used for ADD operations.
   2659   if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
   2660       op != Token::ADD) {
   2661     new_left = new_right = BinaryOpIC::GENERIC;
   2662   }
   2663 
   2664   BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
   2665   BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
   2666 
   2667   Maybe<int> previous_fixed_right_arg =
   2668       BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);
   2669 
   2670   int32_t value;
   2671   bool new_has_fixed_right_arg =
   2672       op == Token::MOD &&
   2673       right->ToInt32(&value) &&
   2674       BinaryOpStub::can_encode_arg_value(value) &&
   2675       (previous_overall == BinaryOpIC::UNINITIALIZED ||
   2676        (previous_fixed_right_arg.has_value &&
   2677         previous_fixed_right_arg.value == value));
   2678   Maybe<int32_t> new_fixed_right_arg(
   2679       new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);
   2680 
   2681   if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) {
   2682     if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
   2683       if (op == Token::DIV ||
   2684           op == Token::MUL ||
   2685           op == Token::SHR ||
   2686           kSmiValueSize == 32) {
   2687         // Arithmetic on two Smi inputs has yielded a heap number.
   2688         // That is the only way to get here from the Smi stub.
   2689         // With 32-bit Smis, all overflows give heap numbers, but with
   2690         // 31-bit Smis, most operations overflow to int32 results.
   2691         result_type = BinaryOpIC::NUMBER;
   2692       } else {
   2693         // Other operations on SMIs that overflow yield int32s.
   2694         result_type = BinaryOpIC::INT32;
   2695       }
   2696     }
   2697     if (new_overall == BinaryOpIC::INT32 &&
   2698         previous_overall == BinaryOpIC::INT32) {
   2699       if (new_left == previous_left && new_right == previous_right) {
   2700         result_type = BinaryOpIC::NUMBER;
   2701       }
   2702     }
   2703   }
   2704 
   2705   BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
   2706   Handle<Code> code = stub.GetCode(isolate);
   2707   if (!code.is_null()) {
   2708 #ifdef DEBUG
   2709     if (FLAG_trace_ic) {
   2710       PrintF("[BinaryOpIC in ");
   2711       JavaScriptFrame::PrintTop(isolate, stdout, false, true);
   2712       PrintF(" ");
   2713       TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
   2714                     previous_result);
   2715       PrintF(" => ");
   2716       TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
   2717       PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
   2718     }
   2719 #endif
   2720     BinaryOpIC ic(isolate);
   2721     ic.patch(*code);
   2722 
   2723     // Activate inlined smi code.
   2724     if (previous_overall == BinaryOpIC::UNINITIALIZED) {
   2725       PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
   2726     }
   2727   }
   2728 
   2729   Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
   2730   Object* builtin = NULL;  // Initialization calms down the compiler.
   2731   switch (op) {
   2732     case Token::ADD:
   2733       builtin = builtins->javascript_builtin(Builtins::ADD);
   2734       break;
   2735     case Token::SUB:
   2736       builtin = builtins->javascript_builtin(Builtins::SUB);
   2737       break;
   2738     case Token::MUL:
   2739       builtin = builtins->javascript_builtin(Builtins::MUL);
   2740       break;
   2741     case Token::DIV:
   2742       builtin = builtins->javascript_builtin(Builtins::DIV);
   2743       break;
   2744     case Token::MOD:
   2745       builtin = builtins->javascript_builtin(Builtins::MOD);
   2746       break;
   2747     case Token::BIT_AND:
   2748       builtin = builtins->javascript_builtin(Builtins::BIT_AND);
   2749       break;
   2750     case Token::BIT_OR:
   2751       builtin = builtins->javascript_builtin(Builtins::BIT_OR);
   2752       break;
   2753     case Token::BIT_XOR:
   2754       builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
   2755       break;
   2756     case Token::SHR:
   2757       builtin = builtins->javascript_builtin(Builtins::SHR);
   2758       break;
   2759     case Token::SAR:
   2760       builtin = builtins->javascript_builtin(Builtins::SAR);
   2761       break;
   2762     case Token::SHL:
   2763       builtin = builtins->javascript_builtin(Builtins::SHL);
   2764       break;
   2765     default:
   2766       UNREACHABLE();
   2767   }
   2768 
   2769   Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
   2770 
   2771   bool caught_exception;
   2772   Handle<Object> builtin_args[] = { right };
   2773   Handle<Object> result = Execution::Call(builtin_function,
   2774                                           left,
   2775                                           ARRAY_SIZE(builtin_args),
   2776                                           builtin_args,
   2777                                           &caught_exception);
   2778   if (caught_exception) {
   2779     return Failure::Exception();
   2780   }
   2781   return *result;
   2782 }
   2783 
   2784 
   2785 Code* CompareIC::GetRawUninitialized(Token::Value op) {
   2786   ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
   2787   Code* code = NULL;
   2788   CHECK(stub.FindCodeInCache(&code, Isolate::Current()));
   2789   return code;
   2790 }
   2791 
   2792 
   2793 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
   2794   ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
   2795   return stub.GetCode(isolate);
   2796 }
   2797 
   2798 
   2799 const char* CompareIC::GetStateName(State state) {
   2800   switch (state) {
   2801     case UNINITIALIZED: return "UNINITIALIZED";
   2802     case SMI: return "SMI";
   2803     case NUMBER: return "NUMBER";
   2804     case INTERNALIZED_STRING: return "INTERNALIZED_STRING";
   2805     case STRING: return "STRING";
   2806     case UNIQUE_NAME: return "UNIQUE_NAME";
   2807     case OBJECT: return "OBJECT";
   2808     case KNOWN_OBJECT: return "KNOWN_OBJECT";
   2809     case GENERIC: return "GENERIC";
   2810   }
   2811   UNREACHABLE();
   2812   return NULL;
   2813 }
   2814 
   2815 
   2816 Handle<Type> CompareIC::StateToType(
   2817     Isolate* isolate,
   2818     CompareIC::State state,
   2819     Handle<Map> map) {
   2820   switch (state) {
   2821     case CompareIC::UNINITIALIZED:
   2822       return handle(Type::None(), isolate);
   2823     case CompareIC::SMI:
   2824       return handle(Type::Smi(), isolate);
   2825     case CompareIC::NUMBER:
   2826       return handle(Type::Number(), isolate);
   2827     case CompareIC::STRING:
   2828       return handle(Type::String(), isolate);
   2829     case CompareIC::INTERNALIZED_STRING:
   2830       return handle(Type::InternalizedString(), isolate);
   2831     case CompareIC::UNIQUE_NAME:
   2832       return handle(Type::UniqueName(), isolate);
   2833     case CompareIC::OBJECT:
   2834       return handle(Type::Receiver(), isolate);
   2835     case CompareIC::KNOWN_OBJECT:
   2836       return handle(
   2837           map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
   2838     case CompareIC::GENERIC:
   2839       return handle(Type::Any(), isolate);
   2840   }
   2841   UNREACHABLE();
   2842   return Handle<Type>();
   2843 }
   2844 
   2845 
   2846 void CompareIC::StubInfoToType(int stub_minor_key,
   2847                                Handle<Type>* left_type,
   2848                                Handle<Type>* right_type,
   2849                                Handle<Type>* overall_type,
   2850                                Handle<Map> map,
   2851                                Isolate* isolate) {
   2852   State left_state, right_state, handler_state;
   2853   ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
   2854                                 &handler_state, NULL);
   2855   *left_type = StateToType(isolate, left_state);
   2856   *right_type = StateToType(isolate, right_state);
   2857   *overall_type = StateToType(isolate, handler_state, map);
   2858 }
   2859 
   2860 
   2861 CompareIC::State CompareIC::NewInputState(State old_state,
   2862                                           Handle<Object> value) {
   2863   switch (old_state) {
   2864     case UNINITIALIZED:
   2865       if (value->IsSmi()) return SMI;
   2866       if (value->IsHeapNumber()) return NUMBER;
   2867       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
   2868       if (value->IsString()) return STRING;
   2869       if (value->IsSymbol()) return UNIQUE_NAME;
   2870       if (value->IsJSObject()) return OBJECT;
   2871       break;
   2872     case SMI:
   2873       if (value->IsSmi()) return SMI;
   2874       if (value->IsHeapNumber()) return NUMBER;
   2875       break;
   2876     case NUMBER:
   2877       if (value->IsNumber()) return NUMBER;
   2878       break;
   2879     case INTERNALIZED_STRING:
   2880       if (value->IsInternalizedString()) return INTERNALIZED_STRING;
   2881       if (value->IsString()) return STRING;
   2882       if (value->IsSymbol()) return UNIQUE_NAME;
   2883       break;
   2884     case STRING:
   2885       if (value->IsString()) return STRING;
   2886       break;
   2887     case UNIQUE_NAME:
   2888       if (value->IsUniqueName()) return UNIQUE_NAME;
   2889       break;
   2890     case OBJECT:
   2891       if (value->IsJSObject()) return OBJECT;
   2892       break;
   2893     case GENERIC:
   2894       break;
   2895     case KNOWN_OBJECT:
   2896       UNREACHABLE();
   2897       break;
   2898   }
   2899   return GENERIC;
   2900 }
   2901 
   2902 
   2903 CompareIC::State CompareIC::TargetState(State old_state,
   2904                                         State old_left,
   2905                                         State old_right,
   2906                                         bool has_inlined_smi_code,
   2907                                         Handle<Object> x,
   2908                                         Handle<Object> y) {
   2909   switch (old_state) {
   2910     case UNINITIALIZED:
   2911       if (x->IsSmi() && y->IsSmi()) return SMI;
   2912       if (x->IsNumber() && y->IsNumber()) return NUMBER;
   2913       if (Token::IsOrderedRelationalCompareOp(op_)) {
   2914         // Ordered comparisons treat undefined as NaN, so the
   2915         // NUMBER stub will do the right thing.
   2916         if ((x->IsNumber() && y->IsUndefined()) ||
   2917             (y->IsNumber() && x->IsUndefined())) {
   2918           return NUMBER;
   2919         }
   2920       }
   2921       if (x->IsInternalizedString() && y->IsInternalizedString()) {
   2922         // We compare internalized strings as plain ones if we need to determine
   2923         // the order in a non-equality compare.
   2924         return Token::IsEqualityOp(op_) ? INTERNALIZED_STRING : STRING;
   2925       }
   2926       if (x->IsString() && y->IsString()) return STRING;
   2927       if (!Token::IsEqualityOp(op_)) return GENERIC;
   2928       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
   2929       if (x->IsJSObject() && y->IsJSObject()) {
   2930         if (Handle<JSObject>::cast(x)->map() ==
   2931             Handle<JSObject>::cast(y)->map()) {
   2932           return KNOWN_OBJECT;
   2933         } else {
   2934           return OBJECT;
   2935         }
   2936       }
   2937       return GENERIC;
   2938     case SMI:
   2939       return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
   2940     case INTERNALIZED_STRING:
   2941       ASSERT(Token::IsEqualityOp(op_));
   2942       if (x->IsString() && y->IsString()) return STRING;
   2943       if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
   2944       return GENERIC;
   2945     case NUMBER:
   2946       // If the failure was due to one side changing from smi to heap number,
   2947       // then keep the state (if other changed at the same time, we will get
   2948       // a second miss and then go to generic).
   2949       if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
   2950       if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
   2951       return GENERIC;
   2952     case KNOWN_OBJECT:
   2953       ASSERT(Token::IsEqualityOp(op_));
   2954       if (x->IsJSObject() && y->IsJSObject()) return OBJECT;
   2955       return GENERIC;
   2956     case STRING:
   2957     case UNIQUE_NAME:
   2958     case OBJECT:
   2959     case GENERIC:
   2960       return GENERIC;
   2961   }
   2962   UNREACHABLE();
   2963   return GENERIC;  // Make the compiler happy.
   2964 }
   2965 
   2966 
   2967 void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
   2968   HandleScope scope(isolate());
   2969   State previous_left, previous_right, previous_state;
   2970   ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
   2971                                 &previous_right, &previous_state, NULL);
   2972   State new_left = NewInputState(previous_left, x);
   2973   State new_right = NewInputState(previous_right, y);
   2974   State state = TargetState(previous_state, previous_left, previous_right,
   2975                             HasInlinedSmiCode(address()), x, y);
   2976   ICCompareStub stub(op_, new_left, new_right, state);
   2977   if (state == KNOWN_OBJECT) {
   2978     stub.set_known_map(
   2979         Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
   2980   }
   2981   set_target(*stub.GetCode(isolate()));
   2982 
   2983 #ifdef DEBUG
   2984   if (FLAG_trace_ic) {
   2985     PrintF("[CompareIC in ");
   2986     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
   2987     PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
   2988            GetStateName(previous_left),
   2989            GetStateName(previous_right),
   2990            GetStateName(previous_state),
   2991            GetStateName(new_left),
   2992            GetStateName(new_right),
   2993            GetStateName(state),
   2994            Token::Name(op_),
   2995            static_cast<void*>(*stub.GetCode(isolate())));
   2996   }
   2997 #endif
   2998 
   2999   // Activate inlined smi code.
   3000   if (previous_state == UNINITIALIZED) {
   3001     PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
   3002   }
   3003 }
   3004 
   3005 
   3006 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
   3007 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
   3008   SealHandleScope shs(isolate);
   3009   ASSERT(args.length() == 3);
   3010   CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
   3011   ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
   3012   return ic.target();
   3013 }
   3014 
   3015 
   3016 void CompareNilIC::Clear(Address address, Code* target) {
   3017   if (target->ic_state() == UNINITIALIZED) return;
   3018   Code::ExtraICState state = target->extended_extra_ic_state();
   3019 
   3020   CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
   3021   stub.ClearState();
   3022 
   3023   Code* code = NULL;
   3024   CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
   3025 
   3026   SetTargetAtAddress(address, code);
   3027 }
   3028 
   3029 
   3030 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
   3031                                             Handle<Object> object) {
   3032   if (object->IsNull() || object->IsUndefined()) {
   3033     return Smi::FromInt(true);
   3034   }
   3035   return Smi::FromInt(object->IsUndetectableObject());
   3036 }
   3037 
   3038 
   3039 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
   3040   Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
   3041 
   3042   CompareNilICStub stub(extra_ic_state);
   3043 
   3044   // Extract the current supported types from the patched IC and calculate what
   3045   // types must be supported as a result of the miss.
   3046   bool already_monomorphic = stub.IsMonomorphic();
   3047 
   3048   stub.UpdateStatus(object);
   3049 
   3050   NilValue nil = stub.GetNilValue();
   3051 
   3052   // Find or create the specialized stub to support the new set of types.
   3053   Handle<Code> code;
   3054   if (stub.IsMonomorphic()) {
   3055     Handle<Map> monomorphic_map(already_monomorphic
   3056                                 ? target()->FindFirstMap()
   3057                                 : HeapObject::cast(*object)->map());
   3058     code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
   3059   } else {
   3060     code = stub.GetCode(isolate());
   3061   }
   3062   set_target(*code);
   3063   return DoCompareNilSlow(nil, object);
   3064 }
   3065 
   3066 
   3067 RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
   3068   HandleScope scope(isolate);
   3069   Handle<Object> object = args.at<Object>(0);
   3070   CompareNilIC ic(isolate);
   3071   return ic.CompareNil(object);
   3072 }
   3073 
   3074 
   3075 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
   3076   UNREACHABLE();
   3077   CHECK(false);
   3078   return isolate->heap()->undefined_value();
   3079 }
   3080 
   3081 
   3082 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
   3083                                     Code::ExtraICState extra_ic_state) {
   3084   ToBooleanStub stub(extra_ic_state);
   3085   bool to_boolean_value = stub.UpdateStatus(object);
   3086   Handle<Code> code = stub.GetCode(isolate());
   3087   set_target(*code);
   3088   return Smi::FromInt(to_boolean_value ? 1 : 0);
   3089 }
   3090 
   3091 
   3092 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
   3093   ASSERT(args.length() == 1);
   3094   HandleScope scope(isolate);
   3095   Handle<Object> object = args.at<Object>(0);
   3096   ToBooleanIC ic(isolate);
   3097   Code::ExtraICState ic_state = ic.target()->extended_extra_ic_state();
   3098   return ic.ToBoolean(object, ic_state);
   3099 }
   3100 
   3101 
   3102 static const Address IC_utilities[] = {
   3103 #define ADDR(name) FUNCTION_ADDR(name),
   3104     IC_UTIL_LIST(ADDR)
   3105     NULL
   3106 #undef ADDR
   3107 };
   3108 
   3109 
   3110 Address IC::AddressFromUtilityId(IC::UtilityId id) {
   3111   return IC_utilities[id];
   3112 }
   3113 
   3114 
   3115 } }  // namespace v8::internal
   3116