Home | History | Annotate | Download | only in ic
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/ic/ic.h"
      6 
      7 #include "src/accessors.h"
      8 #include "src/api.h"
      9 #include "src/arguments.h"
     10 #include "src/base/bits.h"
     11 #include "src/codegen.h"
     12 #include "src/conversions.h"
     13 #include "src/execution.h"
     14 #include "src/frames-inl.h"
     15 #include "src/ic/call-optimization.h"
     16 #include "src/ic/handler-compiler.h"
     17 #include "src/ic/ic-inl.h"
     18 #include "src/ic/ic-compiler.h"
     19 #include "src/ic/stub-cache.h"
     20 #include "src/isolate-inl.h"
     21 #include "src/macro-assembler.h"
     22 #include "src/prototype.h"
     23 #include "src/runtime/runtime.h"
     24 
     25 namespace v8 {
     26 namespace internal {
     27 
     28 char IC::TransitionMarkFromState(IC::State state) {
     29   switch (state) {
     30     case UNINITIALIZED:
     31       return '0';
     32     case PREMONOMORPHIC:
     33       return '.';
     34     case MONOMORPHIC:
     35       return '1';
     36     case PROTOTYPE_FAILURE:
     37       return '^';
     38     case POLYMORPHIC:
     39       return 'P';
     40     case MEGAMORPHIC:
     41       return 'N';
     42     case GENERIC:
     43       return 'G';
     44 
     45     // We never see the debugger states here, because the state is
     46     // computed from the original code - not the patched code. Let
     47     // these cases fall through to the unreachable code below.
     48     case DEBUG_STUB:
     49       break;
     50   }
     51   UNREACHABLE();
     52   return 0;
     53 }
     54 
     55 
     56 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
     57   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
     58   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
     59     return ".IGNORE_OOB";
     60   }
     61   if (IsGrowStoreMode(mode)) return ".GROW";
     62   return "";
     63 }
     64 
     65 
     66 #ifdef DEBUG
     67 
     68 #define TRACE_GENERIC_IC(isolate, type, reason)                \
     69   do {                                                         \
     70     if (FLAG_trace_ic) {                                       \
     71       PrintF("[%s patching generic stub in ", type);           \
     72       JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
     73       PrintF(" (%s)]\n", reason);                              \
     74     }                                                          \
     75   } while (false)
     76 
     77 #else
     78 
     79 #define TRACE_GENERIC_IC(isolate, type, reason)      \
     80   do {                                               \
     81     if (FLAG_trace_ic) {                             \
     82       PrintF("[%s patching generic stub in ", type); \
     83       PrintF("(see below) (%s)]\n", reason);         \
     84     }                                                \
     85   } while (false)
     86 
     87 #endif  // DEBUG
     88 
     89 
     90 void IC::TraceIC(const char* type, Handle<Object> name) {
     91   if (FLAG_trace_ic) {
     92     if (AddressIsDeoptimizedCode()) return;
     93     State new_state =
     94         UseVector() ? nexus()->StateFromFeedback() : raw_target()->ic_state();
     95     TraceIC(type, name, state(), new_state);
     96   }
     97 }
     98 
     99 
    100 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
    101                  State new_state) {
    102   if (FLAG_trace_ic) {
    103     Code* new_target = raw_target();
    104     PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
    105 
    106     // TODO(jkummerow): Add support for "apply". The logic is roughly:
    107     // marker = [fp_ + kMarkerOffset];
    108     // if marker is smi and marker.value == INTERNAL and
    109     //     the frame's code == builtin(Builtins::kFunctionApply):
    110     // then print "apply from" and advance one frame
    111 
    112     Object* maybe_function =
    113         Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
    114     if (maybe_function->IsJSFunction()) {
    115       JSFunction* function = JSFunction::cast(maybe_function);
    116       JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
    117                                               stdout, true);
    118     }
    119 
    120     const char* modifier = "";
    121     if (new_target->kind() == Code::KEYED_STORE_IC) {
    122       KeyedAccessStoreMode mode =
    123           casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
    124       modifier = GetTransitionMarkModifier(mode);
    125     }
    126     PrintF(" (%c->%c%s) ", TransitionMarkFromState(old_state),
    127            TransitionMarkFromState(new_state), modifier);
    128 #ifdef OBJECT_PRINT
    129     OFStream os(stdout);
    130     name->Print(os);
    131 #else
    132     name->ShortPrint(stdout);
    133 #endif
    134     PrintF("]\n");
    135   }
    136 }
    137 
    138 
    139 #define TRACE_IC(type, name) TraceIC(type, name)
    140 
    141 
    142 IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
    143     : isolate_(isolate),
    144       target_set_(false),
    145       vector_set_(false),
    146       target_maps_set_(false),
    147       nexus_(nexus) {
    148   // To improve the performance of the (much used) IC code, we unfold a few
    149   // levels of the stack frame iteration code. This yields a ~35% speedup when
    150   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
    151   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
    152   Address* constant_pool = NULL;
    153   if (FLAG_enable_embedded_constant_pool) {
    154     constant_pool = reinterpret_cast<Address*>(
    155         entry + ExitFrameConstants::kConstantPoolOffset);
    156   }
    157   Address* pc_address =
    158       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
    159   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
    160   // If there's another JavaScript frame on the stack or a
    161   // StubFailureTrampoline, we need to look one frame further down the stack to
    162   // find the frame pointer and the return address stack slot.
    163   if (depth == EXTRA_CALL_FRAME) {
    164     if (FLAG_enable_embedded_constant_pool) {
    165       constant_pool = reinterpret_cast<Address*>(
    166           fp + StandardFrameConstants::kConstantPoolOffset);
    167     }
    168     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
    169     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
    170     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
    171   }
    172 #ifdef DEBUG
    173   StackFrameIterator it(isolate);
    174   for (int i = 0; i < depth + 1; i++) it.Advance();
    175   StackFrame* frame = it.frame();
    176   DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
    177 #endif
    178   fp_ = fp;
    179   if (FLAG_enable_embedded_constant_pool) {
    180     constant_pool_address_ = constant_pool;
    181   }
    182   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
    183   target_ = handle(raw_target(), isolate);
    184   kind_ = target_->kind();
    185   state_ = UseVector() ? nexus->StateFromFeedback() : target_->ic_state();
    186   old_state_ = state_;
    187   extra_ic_state_ = target_->extra_ic_state();
    188 }
    189 
    190 
    191 SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
    192   // Compute the JavaScript frame for the frame pointer of this IC
    193   // structure. We need this to be able to find the function
    194   // corresponding to the frame.
    195   StackFrameIterator it(isolate());
    196   while (it.frame()->fp() != this->fp()) it.Advance();
    197   if (FLAG_ignition && it.frame()->type() == StackFrame::STUB) {
    198     // Advance over bytecode handler frame.
    199     // TODO(rmcilroy): Remove this once bytecode handlers don't need a frame.
    200     it.Advance();
    201   }
    202   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
    203   // Find the function on the stack and both the active code for the
    204   // function and the original code.
    205   JSFunction* function = frame->function();
    206   return function->shared();
    207 }
    208 
    209 
    210 Code* IC::GetCode() const {
    211   HandleScope scope(isolate());
    212   Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
    213   Code* code = shared->code();
    214   return code;
    215 }
    216 
    217 
    218 bool IC::AddressIsOptimizedCode() const {
    219   Code* host =
    220       isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code;
    221   return host->kind() == Code::OPTIMIZED_FUNCTION;
    222 }
    223 
    224 
    225 static void LookupForRead(LookupIterator* it) {
    226   for (; it->IsFound(); it->Next()) {
    227     switch (it->state()) {
    228       case LookupIterator::NOT_FOUND:
    229       case LookupIterator::TRANSITION:
    230         UNREACHABLE();
    231       case LookupIterator::JSPROXY:
    232         return;
    233       case LookupIterator::INTERCEPTOR: {
    234         // If there is a getter, return; otherwise loop to perform the lookup.
    235         Handle<JSObject> holder = it->GetHolder<JSObject>();
    236         if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) {
    237           return;
    238         }
    239         break;
    240       }
    241       case LookupIterator::ACCESS_CHECK:
    242         // PropertyHandlerCompiler::CheckPrototypes() knows how to emit
    243         // access checks for global proxies.
    244         if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
    245           break;
    246         }
    247         return;
    248       case LookupIterator::ACCESSOR:
    249       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    250       case LookupIterator::DATA:
    251         return;
    252     }
    253   }
    254 }
    255 
    256 
    257 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
    258                                                 Handle<String> name) {
    259   if (!IsNameCompatibleWithPrototypeFailure(name)) return false;
    260   if (UseVector()) {
    261     maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
    262   } else {
    263     maybe_handler_ = target()->FindHandlerForMap(*receiver_map());
    264   }
    265 
    266   // The current map wasn't handled yet. There's no reason to stay monomorphic,
    267   // *unless* we're moving from a deprecated map to its replacement, or
    268   // to a more general elements kind.
    269   // TODO(verwaest): Check if the current map is actually what the old map
    270   // would transition to.
    271   if (maybe_handler_.is_null()) {
    272     if (!receiver_map()->IsJSObjectMap()) return false;
    273     Map* first_map = FirstTargetMap();
    274     if (first_map == NULL) return false;
    275     Handle<Map> old_map(first_map);
    276     if (old_map->is_deprecated()) return true;
    277     return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
    278                                                receiver_map()->elements_kind());
    279   }
    280 
    281   CacheHolderFlag flag;
    282   Handle<Map> ic_holder_map(GetICCacheHolder(receiver_map(), isolate(), &flag));
    283 
    284   DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject());
    285   DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver());
    286   DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary);
    287 
    288   if (state() == MONOMORPHIC) {
    289     int index = ic_holder_map->IndexInCodeCache(*name, *target());
    290     if (index >= 0) {
    291       ic_holder_map->RemoveFromCodeCache(*name, *target(), index);
    292     }
    293   }
    294 
    295   if (receiver->IsJSGlobalObject()) {
    296     Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
    297     LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
    298     if (it.state() == LookupIterator::ACCESS_CHECK) return false;
    299     if (!it.IsFound()) return false;
    300     return it.property_details().cell_type() == PropertyCellType::kConstant;
    301   }
    302 
    303   return true;
    304 }
    305 
    306 
    307 bool IC::IsNameCompatibleWithPrototypeFailure(Handle<Object> name) {
    308   if (target()->is_keyed_stub()) {
    309     // Determine whether the failure is due to a name failure.
    310     if (!name->IsName()) return false;
    311     Name* stub_name =
    312         UseVector() ? nexus()->FindFirstName() : target()->FindFirstName();
    313     if (*name != stub_name) return false;
    314   }
    315 
    316   return true;
    317 }
    318 
    319 
    320 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
    321   update_receiver_map(receiver);
    322   if (!name->IsString()) return;
    323   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
    324   if (receiver->IsUndefined() || receiver->IsNull()) return;
    325 
    326   // Remove the target from the code cache if it became invalid
    327   // because of changes in the prototype chain to avoid hitting it
    328   // again.
    329   if (TryRemoveInvalidPrototypeDependentStub(receiver,
    330                                              Handle<String>::cast(name))) {
    331     MarkPrototypeFailure(name);
    332     return;
    333   }
    334 }
    335 
    336 
    337 MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
    338                                   Handle<Object> object, Handle<Object> key) {
    339   HandleScope scope(isolate());
    340   THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
    341 }
    342 
    343 
    344 MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
    345   HandleScope scope(isolate());
    346   THROW_NEW_ERROR(
    347       isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
    348 }
    349 
    350 
    351 static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
    352                                       int* polymorphic_delta,
    353                                       int* generic_delta) {
    354   switch (old_state) {
    355     case UNINITIALIZED:
    356     case PREMONOMORPHIC:
    357       if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
    358       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
    359         *polymorphic_delta = 1;
    360       } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
    361         *generic_delta = 1;
    362       }
    363       break;
    364     case MONOMORPHIC:
    365     case POLYMORPHIC:
    366       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
    367       *polymorphic_delta = -1;
    368       if (new_state == MEGAMORPHIC || new_state == GENERIC) {
    369         *generic_delta = 1;
    370       }
    371       break;
    372     case MEGAMORPHIC:
    373     case GENERIC:
    374       if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
    375       *generic_delta = -1;
    376       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
    377         *polymorphic_delta = 1;
    378       }
    379       break;
    380     case PROTOTYPE_FAILURE:
    381     case DEBUG_STUB:
    382       UNREACHABLE();
    383   }
    384 }
    385 
    386 
    387 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
    388                                State old_state, State new_state,
    389                                bool target_remains_ic_stub) {
    390   Code* host =
    391       isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
    392   if (host->kind() != Code::FUNCTION) return;
    393 
    394   if (FLAG_type_info_threshold > 0 && target_remains_ic_stub &&
    395       // Not all Code objects have TypeFeedbackInfo.
    396       host->type_feedback_info()->IsTypeFeedbackInfo()) {
    397     int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
    398     int generic_delta = 0;      // "Generic" here includes megamorphic.
    399     ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
    400                               &generic_delta);
    401     TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
    402     info->change_ic_with_type_info_count(polymorphic_delta);
    403     info->change_ic_generic_count(generic_delta);
    404   }
    405   if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
    406     TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
    407     info->change_own_type_change_checksum();
    408   }
    409   host->set_profiler_ticks(0);
    410   isolate->runtime_profiler()->NotifyICChanged();
    411   // TODO(2029): When an optimized function is patched, it would
    412   // be nice to propagate the corresponding type information to its
    413   // unoptimized version for the benefit of later inlining.
    414 }
    415 
    416 
    417 // static
    418 void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
    419   if (host->kind() != Code::FUNCTION) return;
    420 
    421   TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
    422   info->change_own_type_change_checksum();
    423   host->set_profiler_ticks(0);
    424   isolate->runtime_profiler()->NotifyICChanged();
    425   // TODO(2029): When an optimized function is patched, it would
    426   // be nice to propagate the corresponding type information to its
    427   // unoptimized version for the benefit of later inlining.
    428 }
    429 
    430 
    431 void IC::PostPatching(Address address, Code* target, Code* old_target) {
    432   // Type vector based ICs update these statistics at a different time because
    433   // they don't always patch on state change.
    434   if (ICUseVector(target->kind())) return;
    435 
    436   Isolate* isolate = target->GetHeap()->isolate();
    437   State old_state = UNINITIALIZED;
    438   State new_state = UNINITIALIZED;
    439   bool target_remains_ic_stub = false;
    440   if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) {
    441     old_state = old_target->ic_state();
    442     new_state = target->ic_state();
    443     target_remains_ic_stub = true;
    444   }
    445 
    446   OnTypeFeedbackChanged(isolate, address, old_state, new_state,
    447                         target_remains_ic_stub);
    448 }
    449 
    450 
    451 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
    452   Code* target = GetTargetAtAddress(address, constant_pool);
    453 
    454   // Don't clear debug break inline cache as it will remove the break point.
    455   if (target->is_debug_stub()) return;
    456 
    457   switch (target->kind()) {
    458     case Code::LOAD_IC:
    459     case Code::KEYED_LOAD_IC:
    460     case Code::STORE_IC:
    461     case Code::KEYED_STORE_IC:
    462       return;
    463     case Code::COMPARE_IC:
    464       return CompareIC::Clear(isolate, address, target, constant_pool);
    465     case Code::COMPARE_NIL_IC:
    466       return CompareNilIC::Clear(address, target, constant_pool);
    467     case Code::CALL_IC:  // CallICs are vector-based and cleared differently.
    468     case Code::BINARY_OP_IC:
    469     case Code::TO_BOOLEAN_IC:
    470       // Clearing these is tricky and does not
    471       // make any performance difference.
    472       return;
    473     default:
    474       UNREACHABLE();
    475   }
    476 }
    477 
    478 
    479 void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
    480   if (IsCleared(nexus)) return;
    481   // Make sure to also clear the map used in inline fast cases.  If we
    482   // do not clear these maps, cached code can keep objects alive
    483   // through the embedded maps.
    484   nexus->ConfigurePremonomorphic();
    485   OnTypeFeedbackChanged(isolate, host);
    486 }
    487 
    488 
    489 void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
    490   // Determine our state.
    491   Object* feedback = nexus->vector()->Get(nexus->slot());
    492   State state = nexus->StateFromFeedback();
    493 
    494   if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
    495     nexus->ConfigureUninitialized();
    496     // The change in state must be processed.
    497     OnTypeFeedbackChanged(isolate, host);
    498   }
    499 }
    500 
    501 
    502 void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
    503   if (IsCleared(nexus)) return;
    504   nexus->ConfigurePremonomorphic();
    505   OnTypeFeedbackChanged(isolate, host);
    506 }
    507 
    508 
    509 void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
    510                     Address constant_pool) {
    511   if (IsCleared(target)) return;
    512   Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC,
    513                                                       target->extra_ic_state());
    514   SetTargetAtAddress(address, code, constant_pool);
    515 }
    516 
    517 
    518 void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
    519   if (IsCleared(nexus)) return;
    520   nexus->ConfigurePremonomorphic();
    521   OnTypeFeedbackChanged(isolate, host);
    522 }
    523 
    524 
    525 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
    526                          Address constant_pool) {
    527   if (IsCleared(target)) return;
    528   Handle<Code> code = pre_monomorphic_stub(
    529       isolate, StoreICState::GetLanguageMode(target->extra_ic_state()));
    530   SetTargetAtAddress(address, *code, constant_pool);
    531 }
    532 
    533 
    534 void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
    535                          KeyedStoreICNexus* nexus) {
    536   if (IsCleared(nexus)) return;
    537   nexus->ConfigurePremonomorphic();
    538   OnTypeFeedbackChanged(isolate, host);
    539 }
    540 
    541 
    542 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
    543                       Address constant_pool) {
    544   DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
    545   CompareICStub stub(target->stub_key(), isolate);
    546   // Only clear CompareICs that can retain objects.
    547   if (stub.state() != CompareICState::KNOWN_RECEIVER) return;
    548   SetTargetAtAddress(address,
    549                      GetRawUninitialized(isolate, stub.op(), stub.strength()),
    550                      constant_pool);
    551   PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
    552 }
    553 
    554 
    555 // static
    556 Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
    557                                                 ExtraICState extra_state) {
    558   if (FLAG_compiled_keyed_generic_loads) {
    559     return KeyedLoadGenericStub(isolate, LoadICState(extra_state)).GetCode();
    560   } else {
    561     return is_strong(LoadICState::GetLanguageMode(extra_state))
    562                ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong()
    563                : isolate->builtins()->KeyedLoadIC_Megamorphic();
    564   }
    565 }
    566 
    567 
    568 static bool MigrateDeprecated(Handle<Object> object) {
    569   if (!object->IsJSObject()) return false;
    570   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    571   if (!receiver->map()->is_deprecated()) return false;
    572   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
    573   return true;
    574 }
    575 
    576 
    577 void IC::ConfigureVectorState(IC::State new_state) {
    578   DCHECK(UseVector());
    579   if (new_state == PREMONOMORPHIC) {
    580     nexus()->ConfigurePremonomorphic();
    581   } else if (new_state == MEGAMORPHIC) {
    582     nexus()->ConfigureMegamorphic();
    583   } else {
    584     UNREACHABLE();
    585   }
    586 
    587   vector_set_ = true;
    588   OnTypeFeedbackChanged(isolate(), get_host());
    589 }
    590 
    591 
    592 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
    593                               Handle<Code> handler) {
    594   DCHECK(UseVector());
    595   if (kind() == Code::LOAD_IC) {
    596     LoadICNexus* nexus = casted_nexus<LoadICNexus>();
    597     nexus->ConfigureMonomorphic(map, handler);
    598   } else if (kind() == Code::KEYED_LOAD_IC) {
    599     KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
    600     nexus->ConfigureMonomorphic(name, map, handler);
    601   } else if (kind() == Code::STORE_IC) {
    602     StoreICNexus* nexus = casted_nexus<StoreICNexus>();
    603     nexus->ConfigureMonomorphic(map, handler);
    604   } else {
    605     DCHECK(kind() == Code::KEYED_STORE_IC);
    606     KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
    607     nexus->ConfigureMonomorphic(name, map, handler);
    608   }
    609 
    610   vector_set_ = true;
    611   OnTypeFeedbackChanged(isolate(), get_host());
    612 }
    613 
    614 
    615 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
    616                               CodeHandleList* handlers) {
    617   DCHECK(UseVector());
    618   if (kind() == Code::LOAD_IC) {
    619     LoadICNexus* nexus = casted_nexus<LoadICNexus>();
    620     nexus->ConfigurePolymorphic(maps, handlers);
    621   } else if (kind() == Code::KEYED_LOAD_IC) {
    622     KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
    623     nexus->ConfigurePolymorphic(name, maps, handlers);
    624   } else if (kind() == Code::STORE_IC) {
    625     StoreICNexus* nexus = casted_nexus<StoreICNexus>();
    626     nexus->ConfigurePolymorphic(maps, handlers);
    627   } else {
    628     DCHECK(kind() == Code::KEYED_STORE_IC);
    629     KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
    630     nexus->ConfigurePolymorphic(name, maps, handlers);
    631   }
    632 
    633   vector_set_ = true;
    634   OnTypeFeedbackChanged(isolate(), get_host());
    635 }
    636 
    637 
    638 void IC::ConfigureVectorState(MapHandleList* maps,
    639                               MapHandleList* transitioned_maps,
    640                               CodeHandleList* handlers) {
    641   DCHECK(UseVector());
    642   DCHECK(kind() == Code::KEYED_STORE_IC);
    643   KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
    644   nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
    645 
    646   vector_set_ = true;
    647   OnTypeFeedbackChanged(isolate(), get_host());
    648 }
    649 
    650 
    651 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
    652   // If the object is undefined or null it's illegal to try to get any
    653   // of its properties; throw a TypeError in that case.
    654   if (object->IsUndefined() || object->IsNull()) {
    655     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
    656   }
    657 
    658   // Check if the name is trivially convertible to an index and get
    659   // the element or char if so.
    660   uint32_t index;
    661   if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
    662     // Rewrite to the generic keyed load stub.
    663     if (FLAG_use_ic) {
    664       DCHECK(UseVector());
    665       ConfigureVectorState(MEGAMORPHIC);
    666       TRACE_IC("LoadIC", name);
    667       TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
    668     }
    669     Handle<Object> result;
    670     ASSIGN_RETURN_ON_EXCEPTION(
    671         isolate(), result,
    672         Object::GetElement(isolate(), object, index, language_mode()), Object);
    673     return result;
    674   }
    675 
    676   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
    677 
    678   if (object->IsJSGlobalObject() && name->IsString()) {
    679     // Look up in script context table.
    680     Handle<String> str_name = Handle<String>::cast(name);
    681     Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
    682     Handle<ScriptContextTable> script_contexts(
    683         global->native_context()->script_context_table());
    684 
    685     ScriptContextTable::LookupResult lookup_result;
    686     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
    687       Handle<Object> result =
    688           FixedArray::get(ScriptContextTable::GetContext(
    689                               script_contexts, lookup_result.context_index),
    690                           lookup_result.slot_index);
    691       if (*result == *isolate()->factory()->the_hole_value()) {
    692         // Do not install stubs and stay pre-monomorphic for
    693         // uninitialized accesses.
    694         return ReferenceError(name);
    695       }
    696 
    697       if (use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
    698         LoadScriptContextFieldStub stub(isolate(), &lookup_result);
    699         PatchCache(name, stub.GetCode());
    700       }
    701       return result;
    702     }
    703   }
    704 
    705   // Named lookup in the object.
    706   LookupIterator it(object, name);
    707   LookupForRead(&it);
    708 
    709   if (it.IsFound() || !ShouldThrowReferenceError(object)) {
    710     // Update inline cache and stub cache.
    711     if (use_ic) UpdateCaches(&it);
    712 
    713     // Get the property.
    714     Handle<Object> result;
    715 
    716     ASSIGN_RETURN_ON_EXCEPTION(
    717         isolate(), result, Object::GetProperty(&it, language_mode()), Object);
    718     if (it.IsFound()) {
    719       return result;
    720     } else if (!ShouldThrowReferenceError(object)) {
    721       LOG(isolate(), SuspectReadEvent(*name, *object));
    722       return result;
    723     }
    724   }
    725   return ReferenceError(name);
    726 }
    727 
    728 
    729 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
    730                                        Handle<Map> new_receiver_map) {
    731   DCHECK(!new_receiver_map.is_null());
    732   for (int current = 0; current < receiver_maps->length(); ++current) {
    733     if (!receiver_maps->at(current).is_null() &&
    734         receiver_maps->at(current).is_identical_to(new_receiver_map)) {
    735       return false;
    736     }
    737   }
    738   receiver_maps->Add(new_receiver_map);
    739   return true;
    740 }
    741 
    742 
    743 bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
    744   if (!code->is_handler()) return false;
    745   if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false;
    746   Handle<Map> map = receiver_map();
    747   MapHandleList maps;
    748   CodeHandleList handlers;
    749 
    750   TargetMaps(&maps);
    751   int number_of_maps = maps.length();
    752   int deprecated_maps = 0;
    753   int handler_to_overwrite = -1;
    754 
    755   for (int i = 0; i < number_of_maps; i++) {
    756     Handle<Map> current_map = maps.at(i);
    757     if (current_map->is_deprecated()) {
    758       // Filter out deprecated maps to ensure their instances get migrated.
    759       ++deprecated_maps;
    760     } else if (map.is_identical_to(current_map)) {
    761       // If the receiver type is already in the polymorphic IC, this indicates
    762       // there was a prototoype chain failure. In that case, just overwrite the
    763       // handler.
    764       handler_to_overwrite = i;
    765     } else if (handler_to_overwrite == -1 &&
    766                IsTransitionOfMonomorphicTarget(*current_map, *map)) {
    767       handler_to_overwrite = i;
    768     }
    769   }
    770 
    771   int number_of_valid_maps =
    772       number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
    773 
    774   if (number_of_valid_maps >= 4) return false;
    775   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
    776     return false;
    777   }
    778   if (UseVector()) {
    779     if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
    780   } else {
    781     if (!target()->FindHandlers(&handlers, maps.length())) return false;
    782   }
    783 
    784   number_of_valid_maps++;
    785   if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false;
    786   Handle<Code> ic;
    787   if (number_of_valid_maps == 1) {
    788     ConfigureVectorState(name, receiver_map(), code);
    789   } else {
    790     if (handler_to_overwrite >= 0) {
    791       handlers.Set(handler_to_overwrite, code);
    792       if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
    793         maps.Set(handler_to_overwrite, map);
    794       }
    795     } else {
    796       maps.Add(map);
    797       handlers.Add(code);
    798     }
    799 
    800     ConfigureVectorState(name, &maps, &handlers);
    801   }
    802 
    803   if (!UseVector()) set_target(*ic);
    804   return true;
    805 }
    806 
    807 
    808 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
    809   DCHECK(handler->is_handler());
    810   ConfigureVectorState(name, receiver_map(), handler);
    811 }
    812 
    813 
    814 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
    815   MapHandleList maps;
    816   CodeHandleList handlers;
    817   TargetMaps(&maps);
    818   if (!target()->FindHandlers(&handlers, maps.length())) return;
    819   for (int i = 0; i < maps.length(); i++) {
    820     UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
    821   }
    822 }
    823 
    824 
    825 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
    826   if (source_map == NULL) return true;
    827   if (target_map == NULL) return false;
    828   ElementsKind target_elements_kind = target_map->elements_kind();
    829   bool more_general_transition = IsMoreGeneralElementsKindTransition(
    830       source_map->elements_kind(), target_elements_kind);
    831   Map* transitioned_map =
    832       more_general_transition
    833           ? source_map->LookupElementsTransitionMap(target_elements_kind)
    834           : NULL;
    835 
    836   return transitioned_map == target_map;
    837 }
    838 
    839 
    840 void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
    841   switch (state()) {
    842     case UNINITIALIZED:
    843     case PREMONOMORPHIC:
    844       UpdateMonomorphicIC(code, name);
    845       break;
    846     case PROTOTYPE_FAILURE:
    847     case MONOMORPHIC:
    848     case POLYMORPHIC:
    849       if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
    850         if (UpdatePolymorphicIC(name, code)) break;
    851         // For keyed stubs, we can't know whether old handlers were for the
    852         // same key.
    853         CopyICToMegamorphicCache(name);
    854       }
    855       if (UseVector()) {
    856         ConfigureVectorState(MEGAMORPHIC);
    857       } else {
    858         set_target(*megamorphic_stub());
    859       }
    860     // Fall through.
    861     case MEGAMORPHIC:
    862       UpdateMegamorphicCache(*receiver_map(), *name, *code);
    863       // Indicate that we've handled this case.
    864       if (UseVector()) {
    865         vector_set_ = true;
    866       } else {
    867         target_set_ = true;
    868       }
    869       break;
    870     case DEBUG_STUB:
    871       break;
    872     case GENERIC:
    873       UNREACHABLE();
    874       break;
    875   }
    876 }
    877 
    878 
    879 Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
    880                                      ExtraICState extra_state) {
    881   return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
    882 }
    883 
    884 
    885 Handle<Code> LoadIC::initialize_stub_in_optimized_code(
    886     Isolate* isolate, ExtraICState extra_state, State initialization_state) {
    887   return LoadICStub(isolate, LoadICState(extra_state)).GetCode();
    888 }
    889 
    890 
    891 Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate,
    892                                           ExtraICState extra_state) {
    893   return KeyedLoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
    894 }
    895 
    896 
    897 Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
    898     Isolate* isolate, State initialization_state, ExtraICState extra_state) {
    899   if (initialization_state != MEGAMORPHIC) {
    900     return KeyedLoadICStub(isolate, LoadICState(extra_state)).GetCode();
    901   }
    902   return is_strong(LoadICState::GetLanguageMode(extra_state))
    903              ? isolate->builtins()->KeyedLoadIC_Megamorphic_Strong()
    904              : isolate->builtins()->KeyedLoadIC_Megamorphic();
    905 }
    906 
    907 
    908 static Handle<Code> KeyedStoreICInitializeStubHelper(
    909     Isolate* isolate, LanguageMode language_mode,
    910     InlineCacheState initialization_state) {
    911   switch (initialization_state) {
    912     case UNINITIALIZED:
    913       return is_strict(language_mode)
    914                  ? isolate->builtins()->KeyedStoreIC_Initialize_Strict()
    915                  : isolate->builtins()->KeyedStoreIC_Initialize();
    916     case PREMONOMORPHIC:
    917       return is_strict(language_mode)
    918                  ? isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict()
    919                  : isolate->builtins()->KeyedStoreIC_PreMonomorphic();
    920     case MEGAMORPHIC:
    921       return is_strict(language_mode)
    922                  ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
    923                  : isolate->builtins()->KeyedStoreIC_Megamorphic();
    924     default:
    925       UNREACHABLE();
    926   }
    927   return Handle<Code>();
    928 }
    929 
    930 
    931 Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate,
    932                                            LanguageMode language_mode,
    933                                            State initialization_state) {
    934   if (initialization_state != MEGAMORPHIC) {
    935     VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
    936     return stub.GetCode();
    937   }
    938 
    939   return KeyedStoreICInitializeStubHelper(isolate, language_mode,
    940                                           initialization_state);
    941 }
    942 
    943 
    944 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code(
    945     Isolate* isolate, LanguageMode language_mode, State initialization_state) {
    946   if (initialization_state != MEGAMORPHIC) {
    947     VectorKeyedStoreICStub stub(isolate, StoreICState(language_mode));
    948     return stub.GetCode();
    949   }
    950 
    951   return KeyedStoreICInitializeStubHelper(isolate, language_mode,
    952                                           initialization_state);
    953 }
    954 
    955 
    956 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
    957                                                  ExtraICState extra_state) {
    958   LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
    959   return KeyedStoreICInitializeStubHelper(isolate, mode, MEGAMORPHIC);
    960 }
    961 
    962 
    963 Handle<Code> LoadIC::megamorphic_stub() {
    964   DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
    965   return KeyedLoadIC::ChooseMegamorphicStub(isolate(), extra_ic_state());
    966 }
    967 
    968 
    969 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
    970   LoadFieldStub stub(isolate(), index);
    971   return stub.GetCode();
    972 }
    973 
    974 
    975 bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
    976   DCHECK(lookup->state() == LookupIterator::ACCESSOR);
    977   Isolate* isolate = lookup->isolate();
    978   Handle<Object> accessors = lookup->GetAccessors();
    979   if (accessors->IsExecutableAccessorInfo()) {
    980     Handle<ExecutableAccessorInfo> info =
    981         Handle<ExecutableAccessorInfo>::cast(accessors);
    982     if (info->getter() != NULL &&
    983         !ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate, info,
    984                                                          receiver_map)) {
    985       return false;
    986     }
    987   } else if (accessors->IsAccessorPair()) {
    988     Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
    989                           isolate);
    990     Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    991     Handle<Object> receiver = lookup->GetReceiver();
    992     if (getter->IsJSFunction() && holder->HasFastProperties()) {
    993       Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
    994       if (receiver->IsJSObject() || function->shared()->IsBuiltin() ||
    995           !is_sloppy(function->shared()->language_mode())) {
    996         CallOptimization call_optimization(function);
    997         if (call_optimization.is_simple_api_call() &&
    998             !call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) {
    999           return false;
   1000         }
   1001       }
   1002     }
   1003   }
   1004   return true;
   1005 }
   1006 
   1007 
   1008 void LoadIC::UpdateCaches(LookupIterator* lookup) {
   1009   if (state() == UNINITIALIZED) {
   1010     // This is the first time we execute this inline cache. Set the target to
   1011     // the pre monomorphic stub to delay setting the monomorphic state.
   1012     ConfigureVectorState(PREMONOMORPHIC);
   1013     TRACE_IC("LoadIC", lookup->name());
   1014     return;
   1015   }
   1016 
   1017   Handle<Code> code;
   1018   if (lookup->state() == LookupIterator::JSPROXY ||
   1019       lookup->state() == LookupIterator::ACCESS_CHECK) {
   1020     code = slow_stub();
   1021   } else if (!lookup->IsFound()) {
   1022     if (kind() == Code::LOAD_IC && !is_strong(language_mode())) {
   1023       code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
   1024                                                               receiver_map());
   1025       // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
   1026       if (code.is_null()) code = slow_stub();
   1027     } else {
   1028       code = slow_stub();
   1029     }
   1030   } else {
   1031     if (lookup->state() == LookupIterator::ACCESSOR) {
   1032       if (!IsCompatibleReceiver(lookup, receiver_map())) {
   1033         TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
   1034         code = slow_stub();
   1035       }
   1036     } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
   1037       // Perform a lookup behind the interceptor. Copy the LookupIterator since
   1038       // the original iterator will be used to fetch the value.
   1039       LookupIterator it = *lookup;
   1040       it.Next();
   1041       LookupForRead(&it);
   1042       if (it.state() == LookupIterator::ACCESSOR &&
   1043           !IsCompatibleReceiver(&it, receiver_map())) {
   1044         TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
   1045         code = slow_stub();
   1046       }
   1047     }
   1048     if (code.is_null()) code = ComputeHandler(lookup);
   1049   }
   1050 
   1051   PatchCache(lookup->name(), code);
   1052   TRACE_IC("LoadIC", lookup->name());
   1053 }
   1054 
   1055 
   1056 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
   1057   isolate()->stub_cache()->Set(name, map, code);
   1058 }
   1059 
   1060 
   1061 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
   1062   bool receiver_is_holder =
   1063       lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
   1064   CacheHolderFlag flag;
   1065   Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
   1066       receiver_map(), receiver_is_holder, isolate(), &flag);
   1067 
   1068   Handle<Code> code = PropertyHandlerCompiler::Find(
   1069       lookup->name(), stub_holder_map, kind(), flag,
   1070       lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST);
   1071   // Use the cached value if it exists, and if it is different from the
   1072   // handler that just missed.
   1073   if (!code.is_null()) {
   1074     if (!maybe_handler_.is_null() &&
   1075         !maybe_handler_.ToHandleChecked().is_identical_to(code)) {
   1076       return code;
   1077     }
   1078     if (maybe_handler_.is_null()) {
   1079       // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
   1080       // In MEGAMORPHIC case, check if the handler in the megamorphic stub
   1081       // cache (which just missed) is different from the cached handler.
   1082       if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
   1083         Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
   1084         Code* megamorphic_cached_code =
   1085             isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
   1086         if (megamorphic_cached_code != *code) return code;
   1087       } else {
   1088         return code;
   1089       }
   1090     }
   1091   }
   1092 
   1093   code = CompileHandler(lookup, value, flag);
   1094   DCHECK(code->is_handler());
   1095 
   1096   // TODO(mvstanton): we'd only like to cache code on the map when it's custom
   1097   // code compiled for this map, otherwise it's already cached in the global
   1098   // code
   1099   // cache. We are also guarding against installing code with flags that don't
   1100   // match the desired CacheHolderFlag computed above, which would lead to
   1101   // invalid lookups later.
   1102   if (code->type() != Code::NORMAL &&
   1103       Code::ExtractCacheHolderFromFlags(code->flags()) == flag) {
   1104     Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
   1105   }
   1106 
   1107   return code;
   1108 }
   1109 
   1110 
   1111 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
   1112                                     Handle<Object> unused,
   1113                                     CacheHolderFlag cache_holder) {
   1114   Handle<Object> receiver = lookup->GetReceiver();
   1115   if (receiver->IsString() &&
   1116       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
   1117     FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
   1118     return SimpleFieldLoad(index);
   1119   }
   1120 
   1121   if (receiver->IsStringWrapper() &&
   1122       Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
   1123     StringLengthStub string_length_stub(isolate());
   1124     return string_length_stub.GetCode();
   1125   }
   1126 
   1127   // Use specialized code for getting prototype of functions.
   1128   if (receiver->IsJSFunction() &&
   1129       Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
   1130       receiver->IsConstructor() &&
   1131       !Handle<JSFunction>::cast(receiver)
   1132            ->map()
   1133            ->has_non_instance_prototype()) {
   1134     Handle<Code> stub;
   1135     FunctionPrototypeStub function_prototype_stub(isolate());
   1136     return function_prototype_stub.GetCode();
   1137   }
   1138 
   1139   Handle<Map> map = receiver_map();
   1140   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1141   bool receiver_is_holder = receiver.is_identical_to(holder);
   1142   switch (lookup->state()) {
   1143     case LookupIterator::INTERCEPTOR: {
   1144       DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
   1145       NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
   1146       // Perform a lookup behind the interceptor. Copy the LookupIterator since
   1147       // the original iterator will be used to fetch the value.
   1148       LookupIterator it = *lookup;
   1149       it.Next();
   1150       LookupForRead(&it);
   1151       return compiler.CompileLoadInterceptor(&it);
   1152     }
   1153 
   1154     case LookupIterator::ACCESSOR: {
   1155       // Use simple field loads for some well-known callback properties.
   1156       // The method will only return true for absolute truths based on the
   1157       // receiver maps.
   1158       int object_offset;
   1159       if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
   1160                                              &object_offset)) {
   1161         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
   1162         return SimpleFieldLoad(index);
   1163       }
   1164       if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(),
   1165                                                       &object_offset)) {
   1166         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
   1167         ArrayBufferViewLoadFieldStub stub(isolate(), index);
   1168         return stub.GetCode();
   1169       }
   1170 
   1171       Handle<Object> accessors = lookup->GetAccessors();
   1172       if (accessors->IsExecutableAccessorInfo()) {
   1173         Handle<ExecutableAccessorInfo> info =
   1174             Handle<ExecutableAccessorInfo>::cast(accessors);
   1175         if (v8::ToCData<Address>(info->getter()) == 0) break;
   1176         if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info,
   1177                                                              map)) {
   1178           // This case should be already handled in LoadIC::UpdateCaches.
   1179           UNREACHABLE();
   1180           break;
   1181         }
   1182         if (!holder->HasFastProperties()) break;
   1183         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
   1184         return compiler.CompileLoadCallback(lookup->name(), info);
   1185       }
   1186       if (accessors->IsAccessorPair()) {
   1187         Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
   1188                               isolate());
   1189         if (!getter->IsJSFunction()) break;
   1190         if (!holder->HasFastProperties()) break;
   1191         // When debugging we need to go the slow path to flood the accessor.
   1192         if (GetSharedFunctionInfo()->HasDebugInfo()) break;
   1193         Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
   1194         if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() &&
   1195             is_sloppy(function->shared()->language_mode())) {
   1196           // Calling sloppy non-builtins with a value as the receiver
   1197           // requires boxing.
   1198           break;
   1199         }
   1200         CallOptimization call_optimization(function);
   1201         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
   1202         if (call_optimization.is_simple_api_call()) {
   1203           if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
   1204             return compiler.CompileLoadCallback(
   1205                 lookup->name(), call_optimization, lookup->GetAccessorIndex());
   1206           } else {
   1207             // This case should be already handled in LoadIC::UpdateCaches.
   1208             UNREACHABLE();
   1209           }
   1210         }
   1211         int expected_arguments =
   1212             function->shared()->internal_formal_parameter_count();
   1213         return compiler.CompileLoadViaGetter(
   1214             lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
   1215       }
   1216       break;
   1217     }
   1218 
   1219     case LookupIterator::DATA: {
   1220       if (lookup->is_dictionary_holder()) {
   1221         if (kind() != Code::LOAD_IC) break;
   1222         if (holder->IsJSGlobalObject()) {
   1223           NamedLoadHandlerCompiler compiler(isolate(), map, holder,
   1224                                             cache_holder);
   1225           Handle<PropertyCell> cell = lookup->GetPropertyCell();
   1226           Handle<Code> code = compiler.CompileLoadGlobal(
   1227               cell, lookup->name(), lookup->IsConfigurable());
   1228           // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
   1229           CacheHolderFlag flag;
   1230           Handle<Map> stub_holder_map =
   1231               GetHandlerCacheHolder(map, receiver_is_holder, isolate(), &flag);
   1232           Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
   1233           return code;
   1234         }
   1235         // There is only one shared stub for loading normalized
   1236         // properties. It does not traverse the prototype chain, so the
   1237         // property must be found in the object for the stub to be
   1238         // applicable.
   1239         if (!receiver_is_holder) break;
   1240         return is_strong(language_mode())
   1241                    ? isolate()->builtins()->LoadIC_Normal_Strong()
   1242                    : isolate()->builtins()->LoadIC_Normal();
   1243       }
   1244 
   1245       // -------------- Fields --------------
   1246       if (lookup->property_details().type() == DATA) {
   1247         FieldIndex field = lookup->GetFieldIndex();
   1248         if (receiver_is_holder) {
   1249           return SimpleFieldLoad(field);
   1250         }
   1251         NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
   1252         return compiler.CompileLoadField(lookup->name(), field);
   1253       }
   1254 
   1255       // -------------- Constant properties --------------
   1256       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
   1257       if (receiver_is_holder) {
   1258         LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
   1259         return stub.GetCode();
   1260       }
   1261       NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
   1262       return compiler.CompileLoadConstant(lookup->name(),
   1263                                           lookup->GetConstantIndex());
   1264     }
   1265 
   1266     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1267       return slow_stub();
   1268     case LookupIterator::ACCESS_CHECK:
   1269     case LookupIterator::JSPROXY:
   1270     case LookupIterator::NOT_FOUND:
   1271     case LookupIterator::TRANSITION:
   1272       UNREACHABLE();
   1273   }
   1274 
   1275   return slow_stub();
   1276 }
   1277 
   1278 
   1279 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
   1280   // This helper implements a few common fast cases for converting
   1281   // non-smi keys of keyed loads/stores to a smi or a string.
   1282   if (key->IsHeapNumber()) {
   1283     double value = Handle<HeapNumber>::cast(key)->value();
   1284     if (std::isnan(value)) {
   1285       key = isolate->factory()->nan_string();
   1286     } else {
   1287       int int_value = FastD2I(value);
   1288       if (value == int_value && Smi::IsValid(int_value)) {
   1289         key = handle(Smi::FromInt(int_value), isolate);
   1290       }
   1291     }
   1292   } else if (key->IsUndefined()) {
   1293     key = isolate->factory()->undefined_string();
   1294   }
   1295   return key;
   1296 }
   1297 
   1298 
   1299 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
   1300   Handle<Code> null_handle;
   1301   Handle<Map> receiver_map(receiver->map(), isolate());
   1302   MapHandleList target_receiver_maps;
   1303   TargetMaps(&target_receiver_maps);
   1304 
   1305 
   1306   if (target_receiver_maps.length() == 0) {
   1307     Handle<Code> handler =
   1308         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
   1309             receiver_map, extra_ic_state());
   1310     ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
   1311     return null_handle;
   1312   }
   1313 
   1314   // The first time a receiver is seen that is a transitioned version of the
   1315   // previous monomorphic receiver type, assume the new ElementsKind is the
   1316   // monomorphic type. This benefits global arrays that only transition
   1317   // once, and all call sites accessing them are faster if they remain
   1318   // monomorphic. If this optimistic assumption is not true, the IC will
   1319   // miss again and it will become polymorphic and support both the
   1320   // untransitioned and transitioned maps.
   1321   if (state() == MONOMORPHIC && !receiver->IsString() &&
   1322       IsMoreGeneralElementsKindTransition(
   1323           target_receiver_maps.at(0)->elements_kind(),
   1324           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
   1325     Handle<Code> handler =
   1326         PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
   1327             receiver_map, extra_ic_state());
   1328     ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
   1329     return null_handle;
   1330   }
   1331 
   1332   DCHECK(state() != GENERIC);
   1333 
   1334   // Determine the list of receiver maps that this call site has seen,
   1335   // adding the map that was just encountered.
   1336   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
   1337     // If the miss wasn't due to an unseen map, a polymorphic stub
   1338     // won't help, use the generic stub.
   1339     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice");
   1340     return megamorphic_stub();
   1341   }
   1342 
   1343   // If the maximum number of receiver maps has been exceeded, use the generic
   1344   // version of the IC.
   1345   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
   1346     TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded");
   1347     return megamorphic_stub();
   1348   }
   1349 
   1350   CodeHandleList handlers(target_receiver_maps.length());
   1351   ElementHandlerCompiler compiler(isolate());
   1352   compiler.CompileElementHandlers(&target_receiver_maps, &handlers,
   1353                                   language_mode());
   1354   ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
   1355   return null_handle;
   1356 }
   1357 
   1358 
   1359 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
   1360                                       Handle<Object> key) {
   1361   if (MigrateDeprecated(object)) {
   1362     Handle<Object> result;
   1363     ASSIGN_RETURN_ON_EXCEPTION(
   1364         isolate(), result,
   1365         Runtime::GetObjectProperty(isolate(), object, key, language_mode()),
   1366         Object);
   1367     return result;
   1368   }
   1369 
   1370   Handle<Object> load_handle;
   1371   Handle<Code> stub = megamorphic_stub();
   1372 
   1373   // Check for non-string values that can be converted into an
   1374   // internalized string directly or is representable as a smi.
   1375   key = TryConvertKey(key, isolate());
   1376 
   1377   if (key->IsInternalizedString() || key->IsSymbol()) {
   1378     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
   1379                                LoadIC::Load(object, Handle<Name>::cast(key)),
   1380                                Object);
   1381   } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
   1382     if (object->IsJSObject() || (object->IsString() && key->IsNumber())) {
   1383       Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
   1384       if (object->IsString() || key->IsSmi()) stub = LoadElementStub(receiver);
   1385     }
   1386   }
   1387 
   1388   DCHECK(UseVector());
   1389   if (!is_vector_set() || stub.is_null()) {
   1390     Code* generic = *megamorphic_stub();
   1391     if (!stub.is_null() && *stub == generic) {
   1392       ConfigureVectorState(MEGAMORPHIC);
   1393       TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
   1394     }
   1395 
   1396     TRACE_IC("LoadIC", key);
   1397   }
   1398 
   1399   if (!load_handle.is_null()) return load_handle;
   1400 
   1401   Handle<Object> result;
   1402   ASSIGN_RETURN_ON_EXCEPTION(
   1403       isolate(), result,
   1404       Runtime::GetObjectProperty(isolate(), object, key, language_mode()),
   1405       Object);
   1406   return result;
   1407 }
   1408 
   1409 
   1410 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
   1411                              JSReceiver::StoreFromKeyed store_mode) {
   1412   // Disable ICs for non-JSObjects for now.
   1413   Handle<Object> receiver = it->GetReceiver();
   1414   if (!receiver->IsJSObject()) return false;
   1415   DCHECK(!Handle<JSObject>::cast(receiver)->map()->is_deprecated());
   1416 
   1417   for (; it->IsFound(); it->Next()) {
   1418     switch (it->state()) {
   1419       case LookupIterator::NOT_FOUND:
   1420       case LookupIterator::TRANSITION:
   1421         UNREACHABLE();
   1422       case LookupIterator::JSPROXY:
   1423         return false;
   1424       case LookupIterator::INTERCEPTOR: {
   1425         Handle<JSObject> holder = it->GetHolder<JSObject>();
   1426         InterceptorInfo* info = holder->GetNamedInterceptor();
   1427         if (it->HolderIsReceiverOrHiddenPrototype()) {
   1428           if (!info->setter()->IsUndefined()) return true;
   1429         } else if (!info->getter()->IsUndefined() ||
   1430                    !info->query()->IsUndefined()) {
   1431           return false;
   1432         }
   1433         break;
   1434       }
   1435       case LookupIterator::ACCESS_CHECK:
   1436         if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
   1437         break;
   1438       case LookupIterator::ACCESSOR:
   1439         return !it->IsReadOnly();
   1440       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1441         return false;
   1442       case LookupIterator::DATA: {
   1443         if (it->IsReadOnly()) return false;
   1444         Handle<JSObject> holder = it->GetHolder<JSObject>();
   1445         if (receiver.is_identical_to(holder)) {
   1446           it->PrepareForDataProperty(value);
   1447           // The previous receiver map might just have been deprecated,
   1448           // so reload it.
   1449           update_receiver_map(receiver);
   1450           return true;
   1451         }
   1452 
   1453         // Receiver != holder.
   1454         PrototypeIterator iter(it->isolate(), receiver);
   1455         if (receiver->IsJSGlobalProxy()) {
   1456           return it->GetHolder<Object>().is_identical_to(
   1457               PrototypeIterator::GetCurrent(iter));
   1458         }
   1459 
   1460         if (it->HolderIsReceiverOrHiddenPrototype()) return false;
   1461 
   1462         it->PrepareTransitionToDataProperty(value, NONE, store_mode);
   1463         return it->IsCacheableTransition();
   1464       }
   1465     }
   1466   }
   1467 
   1468   it->PrepareTransitionToDataProperty(value, NONE, store_mode);
   1469   return it->IsCacheableTransition();
   1470 }
   1471 
   1472 
   1473 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
   1474                                    Handle<Object> value,
   1475                                    JSReceiver::StoreFromKeyed store_mode) {
   1476   // Check if the name is trivially convertible to an index and set the element.
   1477   uint32_t index;
   1478   if (kind() == Code::KEYED_STORE_IC && name->AsArrayIndex(&index)) {
   1479     // Rewrite to the generic keyed store stub.
   1480     if (FLAG_use_ic) {
   1481       if (UseVector()) {
   1482         ConfigureVectorState(MEGAMORPHIC);
   1483       } else if (!AddressIsDeoptimizedCode()) {
   1484         set_target(*megamorphic_stub());
   1485       }
   1486       TRACE_IC("StoreIC", name);
   1487       TRACE_GENERIC_IC(isolate(), "StoreIC", "name as array index");
   1488     }
   1489     Handle<Object> result;
   1490     ASSIGN_RETURN_ON_EXCEPTION(
   1491         isolate(), result,
   1492         Object::SetElement(isolate(), object, index, value, language_mode()),
   1493         Object);
   1494     return result;
   1495   }
   1496 
   1497   if (object->IsJSGlobalObject() && name->IsString()) {
   1498     // Look up in script context table.
   1499     Handle<String> str_name = Handle<String>::cast(name);
   1500     Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
   1501     Handle<ScriptContextTable> script_contexts(
   1502         global->native_context()->script_context_table());
   1503 
   1504     ScriptContextTable::LookupResult lookup_result;
   1505     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
   1506       Handle<Context> script_context = ScriptContextTable::GetContext(
   1507           script_contexts, lookup_result.context_index);
   1508       if (lookup_result.mode == CONST) {
   1509         return TypeError(MessageTemplate::kConstAssign, object, name);
   1510       }
   1511 
   1512       Handle<Object> previous_value =
   1513           FixedArray::get(script_context, lookup_result.slot_index);
   1514 
   1515       if (*previous_value == *isolate()->factory()->the_hole_value()) {
   1516         // Do not install stubs and stay pre-monomorphic for
   1517         // uninitialized accesses.
   1518         return ReferenceError(name);
   1519       }
   1520 
   1521       if (FLAG_use_ic &&
   1522           StoreScriptContextFieldStub::Accepted(&lookup_result)) {
   1523         StoreScriptContextFieldStub stub(isolate(), &lookup_result);
   1524         PatchCache(name, stub.GetCode());
   1525       }
   1526 
   1527       script_context->set(lookup_result.slot_index, *value);
   1528       return value;
   1529     }
   1530   }
   1531 
   1532   // TODO(verwaest): Let SetProperty do the migration, since storing a property
   1533   // might deprecate the current map again, if value does not fit.
   1534   if (MigrateDeprecated(object) || object->IsJSProxy()) {
   1535     Handle<Object> result;
   1536     ASSIGN_RETURN_ON_EXCEPTION(
   1537         isolate(), result,
   1538         Object::SetProperty(object, name, value, language_mode()), Object);
   1539     return result;
   1540   }
   1541 
   1542   // If the object is undefined or null it's illegal to try to set any
   1543   // properties on it; throw a TypeError in that case.
   1544   if (object->IsUndefined() || object->IsNull()) {
   1545     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
   1546   }
   1547 
   1548   // Observed objects are always modified through the runtime.
   1549   if (object->IsHeapObject() &&
   1550       Handle<HeapObject>::cast(object)->map()->is_observed()) {
   1551     Handle<Object> result;
   1552     ASSIGN_RETURN_ON_EXCEPTION(
   1553         isolate(), result,
   1554         Object::SetProperty(object, name, value, language_mode(), store_mode),
   1555         Object);
   1556     return result;
   1557   }
   1558 
   1559   LookupIterator it(object, name);
   1560   if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
   1561 
   1562   MAYBE_RETURN_NULL(
   1563       Object::SetProperty(&it, value, language_mode(), store_mode));
   1564   return value;
   1565 }
   1566 
   1567 
   1568 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc,
   1569                                      ConvertReceiverMode mode) {
   1570   CallICTrampolineStub stub(isolate, CallICState(argc, mode));
   1571   Handle<Code> code = stub.GetCode();
   1572   return code;
   1573 }
   1574 
   1575 
   1576 Handle<Code> CallIC::initialize_stub_in_optimized_code(
   1577     Isolate* isolate, int argc, ConvertReceiverMode mode) {
   1578   CallICStub stub(isolate, CallICState(argc, mode));
   1579   Handle<Code> code = stub.GetCode();
   1580   return code;
   1581 }
   1582 
   1583 
   1584 static Handle<Code> StoreICInitializeStubHelper(
   1585     Isolate* isolate, ExtraICState extra_state,
   1586     InlineCacheState initialization_state) {
   1587   Handle<Code> ic = PropertyICCompiler::ComputeStore(
   1588       isolate, initialization_state, extra_state);
   1589   return ic;
   1590 }
   1591 
   1592 
   1593 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
   1594                                       LanguageMode language_mode,
   1595                                       State initialization_state) {
   1596   DCHECK(initialization_state == UNINITIALIZED ||
   1597          initialization_state == PREMONOMORPHIC ||
   1598          initialization_state == MEGAMORPHIC);
   1599   VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode));
   1600   return stub.GetCode();
   1601 }
   1602 
   1603 
   1604 Handle<Code> StoreIC::initialize_stub_in_optimized_code(
   1605     Isolate* isolate, LanguageMode language_mode, State initialization_state) {
   1606   DCHECK(initialization_state == UNINITIALIZED ||
   1607          initialization_state == PREMONOMORPHIC ||
   1608          initialization_state == MEGAMORPHIC);
   1609   if (initialization_state != MEGAMORPHIC) {
   1610     VectorStoreICStub stub(isolate, StoreICState(language_mode));
   1611     return stub.GetCode();
   1612   }
   1613 
   1614   return StoreICInitializeStubHelper(
   1615       isolate, ComputeExtraICState(language_mode), initialization_state);
   1616 }
   1617 
   1618 
   1619 Handle<Code> StoreIC::megamorphic_stub() {
   1620   if (kind() == Code::STORE_IC) {
   1621     return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC,
   1622                                             extra_ic_state());
   1623   } else {
   1624     DCHECK(kind() == Code::KEYED_STORE_IC);
   1625     if (is_strict(language_mode())) {
   1626       return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict();
   1627     } else {
   1628       return isolate()->builtins()->KeyedStoreIC_Megamorphic();
   1629     }
   1630   }
   1631 }
   1632 
   1633 
   1634 Handle<Code> StoreIC::slow_stub() const {
   1635   if (kind() == Code::STORE_IC) {
   1636     return isolate()->builtins()->StoreIC_Slow();
   1637   } else {
   1638     DCHECK(kind() == Code::KEYED_STORE_IC);
   1639     return isolate()->builtins()->KeyedStoreIC_Slow();
   1640   }
   1641 }
   1642 
   1643 
   1644 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
   1645                                            LanguageMode language_mode) {
   1646   ExtraICState state = ComputeExtraICState(language_mode);
   1647   return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state);
   1648 }
   1649 
   1650 
   1651 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
   1652                            JSReceiver::StoreFromKeyed store_mode) {
   1653   if (state() == UNINITIALIZED) {
   1654     // This is the first time we execute this inline cache. Set the target to
   1655     // the pre monomorphic stub to delay setting the monomorphic state.
   1656     ConfigureVectorState(PREMONOMORPHIC);
   1657     TRACE_IC("StoreIC", lookup->name());
   1658     return;
   1659   }
   1660 
   1661   bool use_ic = LookupForWrite(lookup, value, store_mode);
   1662   if (!use_ic) {
   1663     TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
   1664   }
   1665   Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub();
   1666 
   1667   PatchCache(lookup->name(), code);
   1668   TRACE_IC("StoreIC", lookup->name());
   1669 }
   1670 
   1671 
   1672 static Handle<Code> PropertyCellStoreHandler(
   1673     Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder,
   1674     Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) {
   1675   auto constant_type = Nothing<PropertyCellConstantType>();
   1676   if (type == PropertyCellType::kConstantType) {
   1677     constant_type = Just(cell->GetConstantType());
   1678   }
   1679   StoreGlobalStub stub(isolate, type, constant_type,
   1680                        receiver->IsJSGlobalProxy());
   1681   auto code = stub.GetCodeCopyFromTemplate(holder, cell);
   1682   // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
   1683   HeapObject::UpdateMapCodeCache(receiver, name, code);
   1684   return code;
   1685 }
   1686 
   1687 
   1688 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
   1689                                      Handle<Object> value,
   1690                                      CacheHolderFlag cache_holder) {
   1691   DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
   1692 
   1693   // This is currently guaranteed by checks in StoreIC::Store.
   1694   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
   1695   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1696   DCHECK(!receiver->IsAccessCheckNeeded() ||
   1697          isolate()->IsInternallyUsedPropertyName(lookup->name()));
   1698 
   1699   switch (lookup->state()) {
   1700     case LookupIterator::TRANSITION: {
   1701       auto store_target = lookup->GetStoreTarget();
   1702       if (store_target->IsJSGlobalObject()) {
   1703         // TODO(dcarney): this currently just deopts. Use the transition cell.
   1704         auto cell = isolate()->factory()->NewPropertyCell();
   1705         cell->set_value(*value);
   1706         auto code = PropertyCellStoreHandler(
   1707             isolate(), store_target, Handle<JSGlobalObject>::cast(store_target),
   1708             lookup->name(), cell, PropertyCellType::kConstant);
   1709         cell->set_value(isolate()->heap()->the_hole_value());
   1710         return code;
   1711       }
   1712       Handle<Map> transition = lookup->transition_map();
   1713       // Currently not handled by CompileStoreTransition.
   1714       if (!holder->HasFastProperties()) {
   1715         TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
   1716         break;
   1717       }
   1718 
   1719       DCHECK(lookup->IsCacheableTransition());
   1720       NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
   1721       return compiler.CompileStoreTransition(transition, lookup->name());
   1722     }
   1723 
   1724     case LookupIterator::INTERCEPTOR: {
   1725       DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
   1726       NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
   1727       return compiler.CompileStoreInterceptor(lookup->name());
   1728     }
   1729 
   1730     case LookupIterator::ACCESSOR: {
   1731       if (!holder->HasFastProperties()) {
   1732         TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
   1733         break;
   1734       }
   1735       Handle<Object> accessors = lookup->GetAccessors();
   1736       if (accessors->IsExecutableAccessorInfo()) {
   1737         Handle<ExecutableAccessorInfo> info =
   1738             Handle<ExecutableAccessorInfo>::cast(accessors);
   1739         if (v8::ToCData<Address>(info->setter()) == 0) {
   1740           TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0");
   1741           break;
   1742         }
   1743         if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
   1744             !lookup->HolderIsReceiverOrHiddenPrototype()) {
   1745           TRACE_GENERIC_IC(isolate(), "StoreIC",
   1746                            "special data property in prototype chain");
   1747           break;
   1748         }
   1749         if (!ExecutableAccessorInfo::IsCompatibleReceiverMap(isolate(), info,
   1750                                                              receiver_map())) {
   1751           TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
   1752           break;
   1753         }
   1754         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
   1755         return compiler.CompileStoreCallback(receiver, lookup->name(), info);
   1756       } else if (accessors->IsAccessorPair()) {
   1757         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
   1758                               isolate());
   1759         if (!setter->IsJSFunction()) {
   1760           TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
   1761           break;
   1762         }
   1763         Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
   1764         CallOptimization call_optimization(function);
   1765         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
   1766         if (call_optimization.is_simple_api_call() &&
   1767             call_optimization.IsCompatibleReceiver(receiver, holder)) {
   1768           return compiler.CompileStoreCallback(receiver, lookup->name(),
   1769                                                call_optimization,
   1770                                                lookup->GetAccessorIndex());
   1771         }
   1772         int expected_arguments =
   1773             function->shared()->internal_formal_parameter_count();
   1774         return compiler.CompileStoreViaSetter(receiver, lookup->name(),
   1775                                               lookup->GetAccessorIndex(),
   1776                                               expected_arguments);
   1777       }
   1778       break;
   1779     }
   1780 
   1781     case LookupIterator::DATA: {
   1782       if (lookup->is_dictionary_holder()) {
   1783         if (holder->IsJSGlobalObject()) {
   1784           DCHECK(holder.is_identical_to(receiver) ||
   1785                  receiver->map()->prototype() == *holder);
   1786           auto cell = lookup->GetPropertyCell();
   1787           auto updated_type = PropertyCell::UpdatedType(
   1788               cell, value, lookup->property_details());
   1789           auto code = PropertyCellStoreHandler(
   1790               isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
   1791               lookup->name(), cell, updated_type);
   1792           return code;
   1793         }
   1794         DCHECK(holder.is_identical_to(receiver));
   1795         return isolate()->builtins()->StoreIC_Normal();
   1796       }
   1797 
   1798       // -------------- Fields --------------
   1799       if (lookup->property_details().type() == DATA) {
   1800         bool use_stub = true;
   1801         if (lookup->representation().IsHeapObject()) {
   1802           // Only use a generic stub if no types need to be tracked.
   1803           Handle<HeapType> field_type = lookup->GetFieldType();
   1804           HeapType::Iterator<Map> it = field_type->Classes();
   1805           use_stub = it.Done();
   1806         }
   1807         if (use_stub) {
   1808           StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
   1809                               lookup->representation());
   1810           return stub.GetCode();
   1811         }
   1812         NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
   1813         return compiler.CompileStoreField(lookup);
   1814       }
   1815 
   1816       // -------------- Constant properties --------------
   1817       DCHECK(lookup->property_details().type() == DATA_CONSTANT);
   1818       TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
   1819       break;
   1820     }
   1821 
   1822     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1823     case LookupIterator::ACCESS_CHECK:
   1824     case LookupIterator::JSPROXY:
   1825     case LookupIterator::NOT_FOUND:
   1826       UNREACHABLE();
   1827   }
   1828   return slow_stub();
   1829 }
   1830 
   1831 
   1832 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<Map> receiver_map,
   1833                                             KeyedAccessStoreMode store_mode) {
   1834   Handle<Code> null_handle;
   1835   // Don't handle megamorphic property accesses for INTERCEPTORS or
   1836   // ACCESSOR_CONSTANT
   1837   // via megamorphic stubs, since they don't have a map in their relocation info
   1838   // and so the stubs can't be harvested for the object needed for a map check.
   1839   if (target()->type() != Code::NORMAL) {
   1840     TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type");
   1841     return megamorphic_stub();
   1842   }
   1843 
   1844   MapHandleList target_receiver_maps;
   1845   TargetMaps(&target_receiver_maps);
   1846   if (target_receiver_maps.length() == 0) {
   1847     Handle<Map> monomorphic_map =
   1848         ComputeTransitionedMap(receiver_map, store_mode);
   1849     store_mode = GetNonTransitioningStoreMode(store_mode);
   1850     Handle<Code> handler =
   1851         PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
   1852             monomorphic_map, language_mode(), store_mode);
   1853     ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler);
   1854     return null_handle;
   1855   }
   1856 
   1857   // There are several special cases where an IC that is MONOMORPHIC can still
   1858   // transition to a different GetNonTransitioningStoreMode IC that handles a
   1859   // superset of the original IC. Handle those here if the receiver map hasn't
   1860   // changed or it has transitioned to a more general kind.
   1861   KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
   1862   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
   1863   if (state() == MONOMORPHIC) {
   1864     Handle<Map> transitioned_receiver_map = receiver_map;
   1865     if (IsTransitionStoreMode(store_mode)) {
   1866       transitioned_receiver_map =
   1867           ComputeTransitionedMap(receiver_map, store_mode);
   1868     }
   1869     if ((receiver_map.is_identical_to(previous_receiver_map) &&
   1870          IsTransitionStoreMode(store_mode)) ||
   1871         IsTransitionOfMonomorphicTarget(*previous_receiver_map,
   1872                                         *transitioned_receiver_map)) {
   1873       // If the "old" and "new" maps are in the same elements map family, or
   1874       // if they at least come from the same origin for a transitioning store,
   1875       // stay MONOMORPHIC and use the map for the most generic ElementsKind.
   1876       store_mode = GetNonTransitioningStoreMode(store_mode);
   1877       Handle<Code> handler =
   1878           PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
   1879               transitioned_receiver_map, language_mode(), store_mode);
   1880       ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map,
   1881                            handler);
   1882       return null_handle;
   1883     } else if (receiver_map.is_identical_to(previous_receiver_map) &&
   1884                old_store_mode == STANDARD_STORE &&
   1885                (store_mode == STORE_AND_GROW_NO_TRANSITION ||
   1886                 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1887                 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
   1888       // A "normal" IC that handles stores can switch to a version that can
   1889       // grow at the end of the array, handle OOB accesses or copy COW arrays
   1890       // and still stay MONOMORPHIC.
   1891       Handle<Code> handler =
   1892           PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
   1893               receiver_map, language_mode(), store_mode);
   1894       ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
   1895       return null_handle;
   1896     }
   1897   }
   1898 
   1899   DCHECK(state() != GENERIC);
   1900 
   1901   bool map_added =
   1902       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
   1903 
   1904   if (IsTransitionStoreMode(store_mode)) {
   1905     Handle<Map> transitioned_receiver_map =
   1906         ComputeTransitionedMap(receiver_map, store_mode);
   1907     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
   1908                                             transitioned_receiver_map);
   1909   }
   1910 
   1911   if (!map_added) {
   1912     // If the miss wasn't due to an unseen map, a polymorphic stub
   1913     // won't help, use the megamorphic stub which can handle everything.
   1914     TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice");
   1915     return megamorphic_stub();
   1916   }
   1917 
   1918   // If the maximum number of receiver maps has been exceeded, use the
   1919   // megamorphic version of the IC.
   1920   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
   1921     return megamorphic_stub();
   1922   }
   1923 
   1924   // Make sure all polymorphic handlers have the same store mode, otherwise the
   1925   // megamorphic stub must be used.
   1926   store_mode = GetNonTransitioningStoreMode(store_mode);
   1927   if (old_store_mode != STANDARD_STORE) {
   1928     if (store_mode == STANDARD_STORE) {
   1929       store_mode = old_store_mode;
   1930     } else if (store_mode != old_store_mode) {
   1931       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch");
   1932       return megamorphic_stub();
   1933     }
   1934   }
   1935 
   1936   // If the store mode isn't the standard mode, make sure that all polymorphic
   1937   // receivers are either external arrays, or all "normal" arrays. Otherwise,
   1938   // use the megamorphic stub.
   1939   if (store_mode != STANDARD_STORE) {
   1940     int external_arrays = 0;
   1941     for (int i = 0; i < target_receiver_maps.length(); ++i) {
   1942       if (target_receiver_maps[i]->has_fixed_typed_array_elements()) {
   1943         external_arrays++;
   1944       }
   1945     }
   1946     if (external_arrays != 0 &&
   1947         external_arrays != target_receiver_maps.length()) {
   1948       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
   1949                        "unsupported combination of external and normal arrays");
   1950       return megamorphic_stub();
   1951     }
   1952   }
   1953 
   1954   MapHandleList transitioned_maps(target_receiver_maps.length());
   1955   CodeHandleList handlers(target_receiver_maps.length());
   1956   PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
   1957       &target_receiver_maps, &transitioned_maps, &handlers, store_mode,
   1958       language_mode());
   1959   ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
   1960   return null_handle;
   1961 }
   1962 
   1963 
   1964 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
   1965     Handle<Map> map, KeyedAccessStoreMode store_mode) {
   1966   switch (store_mode) {
   1967     case STORE_TRANSITION_TO_OBJECT:
   1968     case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
   1969       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
   1970                               ? FAST_HOLEY_ELEMENTS
   1971                               : FAST_ELEMENTS;
   1972       return Map::TransitionElementsTo(map, kind);
   1973     }
   1974     case STORE_TRANSITION_TO_DOUBLE:
   1975     case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
   1976       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
   1977                               ? FAST_HOLEY_DOUBLE_ELEMENTS
   1978                               : FAST_DOUBLE_ELEMENTS;
   1979       return Map::TransitionElementsTo(map, kind);
   1980     }
   1981     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
   1982       DCHECK(map->has_fixed_typed_array_elements());
   1983     // Fall through
   1984     case STORE_NO_TRANSITION_HANDLE_COW:
   1985     case STANDARD_STORE:
   1986     case STORE_AND_GROW_NO_TRANSITION:
   1987       return map;
   1988   }
   1989   UNREACHABLE();
   1990   return MaybeHandle<Map>().ToHandleChecked();
   1991 }
   1992 
   1993 
   1994 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
   1995   uint32_t length = 0;
   1996   if (receiver->IsJSArray()) {
   1997     JSArray::cast(*receiver)->length()->ToArrayLength(&length);
   1998   } else {
   1999     length = static_cast<uint32_t>(receiver->elements()->length());
   2000   }
   2001   return index >= length;
   2002 }
   2003 
   2004 
   2005 static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
   2006                                          uint32_t index, Handle<Object> value) {
   2007   bool oob_access = IsOutOfBoundsAccess(receiver, index);
   2008   // Don't consider this a growing store if the store would send the receiver to
   2009   // dictionary mode.
   2010   bool allow_growth = receiver->IsJSArray() && oob_access &&
   2011                       !receiver->WouldConvertToSlowElements(index);
   2012   if (allow_growth) {
   2013     // Handle growing array in stub if necessary.
   2014     if (receiver->HasFastSmiElements()) {
   2015       if (value->IsHeapNumber()) {
   2016         return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
   2017       }
   2018       if (value->IsHeapObject()) {
   2019         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
   2020       }
   2021     } else if (receiver->HasFastDoubleElements()) {
   2022       if (!value->IsSmi() && !value->IsHeapNumber()) {
   2023         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
   2024       }
   2025     }
   2026     return STORE_AND_GROW_NO_TRANSITION;
   2027   } else {
   2028     // Handle only in-bounds elements accesses.
   2029     if (receiver->HasFastSmiElements()) {
   2030       if (value->IsHeapNumber()) {
   2031         return STORE_TRANSITION_TO_DOUBLE;
   2032       } else if (value->IsHeapObject()) {
   2033         return STORE_TRANSITION_TO_OBJECT;
   2034       }
   2035     } else if (receiver->HasFastDoubleElements()) {
   2036       if (!value->IsSmi() && !value->IsHeapNumber()) {
   2037         return STORE_TRANSITION_TO_OBJECT;
   2038       }
   2039     }
   2040     if (!FLAG_trace_external_array_abuse &&
   2041         receiver->map()->has_fixed_typed_array_elements() && oob_access) {
   2042       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
   2043     }
   2044     Heap* heap = receiver->GetHeap();
   2045     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
   2046       return STORE_NO_TRANSITION_HANDLE_COW;
   2047     } else {
   2048       return STANDARD_STORE;
   2049     }
   2050   }
   2051 }
   2052 
   2053 
   2054 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
   2055                                         Handle<Object> key,
   2056                                         Handle<Object> value) {
   2057   // TODO(verwaest): Let SetProperty do the migration, since storing a property
   2058   // might deprecate the current map again, if value does not fit.
   2059   if (MigrateDeprecated(object)) {
   2060     Handle<Object> result;
   2061     ASSIGN_RETURN_ON_EXCEPTION(
   2062         isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
   2063                                                       value, language_mode()),
   2064         Object);
   2065     return result;
   2066   }
   2067 
   2068   // Check for non-string values that can be converted into an
   2069   // internalized string directly or is representable as a smi.
   2070   key = TryConvertKey(key, isolate());
   2071 
   2072   Handle<Object> store_handle;
   2073   Handle<Code> stub = megamorphic_stub();
   2074 
   2075   uint32_t index;
   2076   if ((key->IsInternalizedString() &&
   2077        !String::cast(*key)->AsArrayIndex(&index)) ||
   2078       key->IsSymbol()) {
   2079     ASSIGN_RETURN_ON_EXCEPTION(
   2080         isolate(), store_handle,
   2081         StoreIC::Store(object, Handle<Name>::cast(key), value,
   2082                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
   2083         Object);
   2084     if (!is_vector_set()) {
   2085       ConfigureVectorState(MEGAMORPHIC);
   2086       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
   2087                        "unhandled internalized string key");
   2088       TRACE_IC("StoreIC", key);
   2089     }
   2090     return store_handle;
   2091   }
   2092 
   2093   bool use_ic =
   2094       FLAG_use_ic && !object->IsStringWrapper() &&
   2095       !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() &&
   2096       !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed());
   2097   if (use_ic && !object->IsSmi()) {
   2098     // Don't use ICs for maps of the objects in Array's prototype chain. We
   2099     // expect to be able to trap element sets to objects with those maps in
   2100     // the runtime to enable optimization of element hole access.
   2101     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
   2102     if (heap_object->map()->IsMapInArrayPrototypeChain()) {
   2103       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype");
   2104       use_ic = false;
   2105     }
   2106   }
   2107 
   2108   Handle<Map> old_receiver_map;
   2109   bool sloppy_arguments_elements = false;
   2110   bool key_is_valid_index = false;
   2111   KeyedAccessStoreMode store_mode = STANDARD_STORE;
   2112   if (use_ic && object->IsJSObject()) {
   2113     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   2114     old_receiver_map = handle(receiver->map(), isolate());
   2115     sloppy_arguments_elements =
   2116         !is_sloppy(language_mode()) &&
   2117         receiver->elements()->map() ==
   2118             isolate()->heap()->sloppy_arguments_elements_map();
   2119     if (!sloppy_arguments_elements) {
   2120       key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0;
   2121       if (key_is_valid_index) {
   2122         uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
   2123         store_mode = GetStoreMode(receiver, index, value);
   2124       }
   2125     }
   2126   }
   2127 
   2128   DCHECK(store_handle.is_null());
   2129   ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
   2130                              Runtime::SetObjectProperty(isolate(), object, key,
   2131                                                         value, language_mode()),
   2132                              Object);
   2133 
   2134   if (use_ic) {
   2135     if (!old_receiver_map.is_null()) {
   2136       if (sloppy_arguments_elements) {
   2137         TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver");
   2138       } else if (key_is_valid_index) {
   2139         // We should go generic if receiver isn't a dictionary, but our
   2140         // prototype chain does have dictionary elements. This ensures that
   2141         // other non-dictionary receivers in the polymorphic case benefit
   2142         // from fast path keyed stores.
   2143         if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) {
   2144           stub = StoreElementStub(old_receiver_map, store_mode);
   2145         } else {
   2146           TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
   2147                            "dictionary or proxy prototype");
   2148         }
   2149       } else {
   2150         TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key");
   2151       }
   2152     } else {
   2153       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver");
   2154     }
   2155   }
   2156 
   2157   if (!is_vector_set() || stub.is_null()) {
   2158     Code* megamorphic = *megamorphic_stub();
   2159     if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) {
   2160       ConfigureVectorState(MEGAMORPHIC);
   2161       TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
   2162                        *stub == megamorphic ? "set generic" : "slow stub");
   2163     }
   2164   }
   2165   TRACE_IC("StoreIC", key);
   2166 
   2167   return store_handle;
   2168 }
   2169 
   2170 
   2171 void CallIC::HandleMiss(Handle<Object> function) {
   2172   Handle<Object> name = isolate()->factory()->empty_string();
   2173   CallICNexus* nexus = casted_nexus<CallICNexus>();
   2174   Object* feedback = nexus->GetFeedback();
   2175 
   2176   // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
   2177   DCHECK(!feedback->IsSmi());
   2178 
   2179   if (feedback->IsWeakCell() || !function->IsJSFunction() ||
   2180       feedback->IsAllocationSite()) {
   2181     // We are going generic.
   2182     nexus->ConfigureMegamorphic();
   2183   } else {
   2184     DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()));
   2185     Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
   2186 
   2187     Handle<JSFunction> array_function =
   2188         Handle<JSFunction>(isolate()->native_context()->array_function());
   2189     if (array_function.is_identical_to(js_function)) {
   2190       // Alter the slot.
   2191       nexus->ConfigureMonomorphicArray();
   2192     } else if (js_function->context()->native_context() !=
   2193                *isolate()->native_context()) {
   2194       // Don't collect cross-native context feedback for the CallIC.
   2195       // TODO(bmeurer): We should collect the SharedFunctionInfo as
   2196       // feedback in this case instead.
   2197       nexus->ConfigureMegamorphic();
   2198     } else {
   2199       nexus->ConfigureMonomorphic(js_function);
   2200     }
   2201   }
   2202 
   2203   if (function->IsJSFunction()) {
   2204     Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
   2205     name = handle(js_function->shared()->name(), isolate());
   2206   }
   2207 
   2208   OnTypeFeedbackChanged(isolate(), get_host());
   2209   TRACE_IC("CallIC", name);
   2210 }
   2211 
   2212 
   2213 #undef TRACE_IC
   2214 
   2215 
   2216 // ----------------------------------------------------------------------------
   2217 // Static IC stub generators.
   2218 //
   2219 
   2220 // Used from ic-<arch>.cc.
   2221 RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
   2222   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2223   HandleScope scope(isolate);
   2224   DCHECK(args.length() == 3);
   2225   Handle<Object> function = args.at<Object>(0);
   2226   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
   2227   Handle<Smi> slot = args.at<Smi>(2);
   2228   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2229   CallICNexus nexus(vector, vector_slot);
   2230   CallIC ic(isolate, &nexus);
   2231   ic.HandleMiss(function);
   2232   return *function;
   2233 }
   2234 
   2235 
   2236 // Used from ic-<arch>.cc.
   2237 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
   2238   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2239   HandleScope scope(isolate);
   2240   Handle<Object> receiver = args.at<Object>(0);
   2241   Handle<Name> key = args.at<Name>(1);
   2242   Handle<Object> result;
   2243 
   2244   DCHECK(args.length() == 4);
   2245   Handle<Smi> slot = args.at<Smi>(2);
   2246   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
   2247   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2248   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
   2249   // LoadIC miss handler if the handler misses. Since the vector Nexus is
   2250   // set up outside the IC, handle that here.
   2251   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
   2252     LoadICNexus nexus(vector, vector_slot);
   2253     LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2254     ic.UpdateState(receiver, key);
   2255     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2256   } else {
   2257     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
   2258               vector->GetKind(vector_slot));
   2259     KeyedLoadICNexus nexus(vector, vector_slot);
   2260     KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2261     ic.UpdateState(receiver, key);
   2262     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2263   }
   2264   return *result;
   2265 }
   2266 
   2267 
   2268 // Used from ic-<arch>.cc
   2269 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
   2270   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2271   HandleScope scope(isolate);
   2272   Handle<Object> receiver = args.at<Object>(0);
   2273   Handle<Object> key = args.at<Object>(1);
   2274   Handle<Object> result;
   2275 
   2276   DCHECK(args.length() == 4);
   2277   Handle<Smi> slot = args.at<Smi>(2);
   2278   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
   2279   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2280   KeyedLoadICNexus nexus(vector, vector_slot);
   2281   KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2282   ic.UpdateState(receiver, key);
   2283   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2284   return *result;
   2285 }
   2286 
   2287 
   2288 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
   2289   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2290   HandleScope scope(isolate);
   2291   Handle<Object> receiver = args.at<Object>(0);
   2292   Handle<Object> key = args.at<Object>(1);
   2293   Handle<Object> result;
   2294 
   2295   DCHECK(args.length() == 4);
   2296   Handle<Smi> slot = args.at<Smi>(2);
   2297   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
   2298   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2299   KeyedLoadICNexus nexus(vector, vector_slot);
   2300   KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2301   ic.UpdateState(receiver, key);
   2302   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2303 
   2304   return *result;
   2305 }
   2306 
   2307 
   2308 // Used from ic-<arch>.cc.
   2309 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
   2310   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2311   HandleScope scope(isolate);
   2312   Handle<Object> receiver = args.at<Object>(0);
   2313   Handle<Name> key = args.at<Name>(1);
   2314   Handle<Object> value = args.at<Object>(2);
   2315   Handle<Object> result;
   2316 
   2317   DCHECK(args.length() == 5 || args.length() == 6);
   2318   Handle<Smi> slot = args.at<Smi>(3);
   2319   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
   2320   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2321   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
   2322     StoreICNexus nexus(vector, vector_slot);
   2323     StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2324     ic.UpdateState(receiver, key);
   2325     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2326                                        ic.Store(receiver, key, value));
   2327   } else {
   2328     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
   2329               vector->GetKind(vector_slot));
   2330     KeyedStoreICNexus nexus(vector, vector_slot);
   2331     KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2332     ic.UpdateState(receiver, key);
   2333     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2334                                        ic.Store(receiver, key, value));
   2335   }
   2336   return *result;
   2337 }
   2338 
   2339 
   2340 RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) {
   2341   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2342   HandleScope scope(isolate);
   2343   Handle<Object> receiver = args.at<Object>(0);
   2344   Handle<Name> key = args.at<Name>(1);
   2345   Handle<Object> value = args.at<Object>(2);
   2346   Handle<Object> result;
   2347 
   2348   int length = args.length();
   2349   DCHECK(length == 5 || length == 6);
   2350   // We might have slot and vector, for a normal miss (slot(3), vector(4)).
   2351   // Or, map and vector for a transitioning store miss (map(3), vector(4)).
   2352   // In this case, we need to recover the slot from a virtual register.
   2353   // If length == 6, then a map is included (map(3), slot(4), vector(5)).
   2354   Handle<Smi> slot;
   2355   Handle<TypeFeedbackVector> vector;
   2356   if (length == 5) {
   2357     if (args.at<Object>(3)->IsMap()) {
   2358       vector = args.at<TypeFeedbackVector>(4);
   2359       slot = handle(
   2360           *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()),
   2361           isolate);
   2362     } else {
   2363       vector = args.at<TypeFeedbackVector>(4);
   2364       slot = args.at<Smi>(3);
   2365     }
   2366   } else {
   2367     vector = args.at<TypeFeedbackVector>(5);
   2368     slot = args.at<Smi>(4);
   2369   }
   2370 
   2371   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2372   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
   2373     StoreICNexus nexus(vector, vector_slot);
   2374     StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2375     ic.UpdateState(receiver, key);
   2376     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2377                                        ic.Store(receiver, key, value));
   2378   } else {
   2379     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
   2380               vector->GetKind(vector_slot));
   2381     KeyedStoreICNexus nexus(vector, vector_slot);
   2382     KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2383     ic.UpdateState(receiver, key);
   2384     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2385                                        ic.Store(receiver, key, value));
   2386   }
   2387   return *result;
   2388 }
   2389 
   2390 
   2391 // Used from ic-<arch>.cc.
   2392 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
   2393   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2394   HandleScope scope(isolate);
   2395   Handle<Object> receiver = args.at<Object>(0);
   2396   Handle<Object> key = args.at<Object>(1);
   2397   Handle<Object> value = args.at<Object>(2);
   2398   Handle<Object> result;
   2399 
   2400   DCHECK(args.length() == 5);
   2401   Handle<Smi> slot = args.at<Smi>(3);
   2402   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
   2403   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2404   KeyedStoreICNexus nexus(vector, vector_slot);
   2405   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2406   ic.UpdateState(receiver, key);
   2407   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2408                                      ic.Store(receiver, key, value));
   2409   return *result;
   2410 }
   2411 
   2412 
   2413 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) {
   2414   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2415   HandleScope scope(isolate);
   2416   Handle<Object> receiver = args.at<Object>(0);
   2417   Handle<Object> key = args.at<Object>(1);
   2418   Handle<Object> value = args.at<Object>(2);
   2419   Handle<Object> result;
   2420 
   2421   DCHECK(args.length() == 5);
   2422   Handle<Smi> slot = args.at<Smi>(3);
   2423   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
   2424   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2425   KeyedStoreICNexus nexus(vector, vector_slot);
   2426   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2427   ic.UpdateState(receiver, key);
   2428   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2429                                      ic.Store(receiver, key, value));
   2430   return *result;
   2431 }
   2432 
   2433 
   2434 RUNTIME_FUNCTION(Runtime_StoreIC_Slow) {
   2435   HandleScope scope(isolate);
   2436   DCHECK(args.length() == 5);
   2437   Handle<Object> object = args.at<Object>(0);
   2438   Handle<Object> key = args.at<Object>(1);
   2439   Handle<Object> value = args.at<Object>(2);
   2440   LanguageMode language_mode;
   2441   StoreICNexus nexus(isolate);
   2442   StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2443   language_mode = ic.language_mode();
   2444   Handle<Object> result;
   2445   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2446       isolate, result,
   2447       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
   2448   return *result;
   2449 }
   2450 
   2451 
   2452 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
   2453   HandleScope scope(isolate);
   2454   DCHECK(args.length() == 5);
   2455   Handle<Object> object = args.at<Object>(0);
   2456   Handle<Object> key = args.at<Object>(1);
   2457   Handle<Object> value = args.at<Object>(2);
   2458   LanguageMode language_mode;
   2459   KeyedStoreICNexus nexus(isolate);
   2460   KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2461   language_mode = ic.language_mode();
   2462   Handle<Object> result;
   2463   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2464       isolate, result,
   2465       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
   2466   return *result;
   2467 }
   2468 
   2469 
   2470 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
   2471   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2472   HandleScope scope(isolate);
   2473   // Length == 5 or 6, depending on whether the vector slot
   2474   // is passed in a virtual register or not.
   2475   DCHECK(args.length() == 5 || args.length() == 6);
   2476   Handle<Object> object = args.at<Object>(0);
   2477   Handle<Object> key = args.at<Object>(1);
   2478   Handle<Object> value = args.at<Object>(2);
   2479   Handle<Map> map = args.at<Map>(3);
   2480   LanguageMode language_mode;
   2481   KeyedStoreICNexus nexus(isolate);
   2482   KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2483   language_mode = ic.language_mode();
   2484   if (object->IsJSObject()) {
   2485     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
   2486                                      map->elements_kind());
   2487   }
   2488   Handle<Object> result;
   2489   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2490       isolate, result,
   2491       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
   2492   return *result;
   2493 }
   2494 
   2495 
   2496 MaybeHandle<Object> BinaryOpIC::Transition(
   2497     Handle<AllocationSite> allocation_site, Handle<Object> left,
   2498     Handle<Object> right) {
   2499   BinaryOpICState state(isolate(), target()->extra_ic_state());
   2500 
   2501   // Compute the actual result using the builtin for the binary operation.
   2502   Handle<Object> result;
   2503   switch (state.op()) {
   2504     default:
   2505       UNREACHABLE();
   2506     case Token::ADD:
   2507       ASSIGN_RETURN_ON_EXCEPTION(
   2508           isolate(), result,
   2509           Object::Add(isolate(), left, right, state.strength()), Object);
   2510       break;
   2511     case Token::SUB:
   2512       ASSIGN_RETURN_ON_EXCEPTION(
   2513           isolate(), result,
   2514           Object::Subtract(isolate(), left, right, state.strength()), Object);
   2515       break;
   2516     case Token::MUL:
   2517       ASSIGN_RETURN_ON_EXCEPTION(
   2518           isolate(), result,
   2519           Object::Multiply(isolate(), left, right, state.strength()), Object);
   2520       break;
   2521     case Token::DIV:
   2522       ASSIGN_RETURN_ON_EXCEPTION(
   2523           isolate(), result,
   2524           Object::Divide(isolate(), left, right, state.strength()), Object);
   2525       break;
   2526     case Token::MOD:
   2527       ASSIGN_RETURN_ON_EXCEPTION(
   2528           isolate(), result,
   2529           Object::Modulus(isolate(), left, right, state.strength()), Object);
   2530       break;
   2531     case Token::BIT_OR:
   2532       ASSIGN_RETURN_ON_EXCEPTION(
   2533           isolate(), result,
   2534           Object::BitwiseOr(isolate(), left, right, state.strength()), Object);
   2535       break;
   2536     case Token::BIT_AND:
   2537       ASSIGN_RETURN_ON_EXCEPTION(
   2538           isolate(), result,
   2539           Object::BitwiseAnd(isolate(), left, right, state.strength()), Object);
   2540       break;
   2541     case Token::BIT_XOR:
   2542       ASSIGN_RETURN_ON_EXCEPTION(
   2543           isolate(), result,
   2544           Object::BitwiseXor(isolate(), left, right, state.strength()), Object);
   2545       break;
   2546     case Token::SAR:
   2547       ASSIGN_RETURN_ON_EXCEPTION(
   2548           isolate(), result,
   2549           Object::ShiftRight(isolate(), left, right, state.strength()), Object);
   2550       break;
   2551     case Token::SHR:
   2552       ASSIGN_RETURN_ON_EXCEPTION(
   2553           isolate(), result,
   2554           Object::ShiftRightLogical(isolate(), left, right, state.strength()),
   2555           Object);
   2556       break;
   2557     case Token::SHL:
   2558       ASSIGN_RETURN_ON_EXCEPTION(
   2559           isolate(), result,
   2560           Object::ShiftLeft(isolate(), left, right, state.strength()), Object);
   2561       break;
   2562   }
   2563 
   2564   // Do not try to update the target if the code was marked for lazy
   2565   // deoptimization. (Since we do not relocate addresses in these
   2566   // code objects, an attempt to access the target could fail.)
   2567   if (AddressIsDeoptimizedCode()) {
   2568     return result;
   2569   }
   2570 
   2571   // Execution::Call can execute arbitrary JavaScript, hence potentially
   2572   // update the state of this very IC, so we must update the stored state.
   2573   UpdateTarget();
   2574 
   2575   // Compute the new state.
   2576   BinaryOpICState old_state(isolate(), target()->extra_ic_state());
   2577   state.Update(left, right, result);
   2578 
   2579   // Check if we have a string operation here.
   2580   Handle<Code> target;
   2581   if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
   2582     // Setup the allocation site on-demand.
   2583     if (allocation_site.is_null()) {
   2584       allocation_site = isolate()->factory()->NewAllocationSite();
   2585     }
   2586 
   2587     // Install the stub with an allocation site.
   2588     BinaryOpICWithAllocationSiteStub stub(isolate(), state);
   2589     target = stub.GetCodeCopyFromTemplate(allocation_site);
   2590 
   2591     // Sanity check the trampoline stub.
   2592     DCHECK_EQ(*allocation_site, target->FindFirstAllocationSite());
   2593   } else {
   2594     // Install the generic stub.
   2595     BinaryOpICStub stub(isolate(), state);
   2596     target = stub.GetCode();
   2597 
   2598     // Sanity check the generic stub.
   2599     DCHECK_NULL(target->FindFirstAllocationSite());
   2600   }
   2601   set_target(*target);
   2602 
   2603   if (FLAG_trace_ic) {
   2604     OFStream os(stdout);
   2605     os << "[BinaryOpIC" << old_state << " => " << state << " @ "
   2606        << static_cast<void*>(*target) << " <- ";
   2607     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
   2608     if (!allocation_site.is_null()) {
   2609       os << " using allocation site " << static_cast<void*>(*allocation_site);
   2610     }
   2611     os << "]" << std::endl;
   2612   }
   2613 
   2614   // Patch the inlined smi code as necessary.
   2615   if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
   2616     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
   2617   } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
   2618     PatchInlinedSmiCode(isolate(), address(), DISABLE_INLINED_SMI_CHECK);
   2619   }
   2620 
   2621   return result;
   2622 }
   2623 
   2624 
   2625 RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
   2626   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2627   HandleScope scope(isolate);
   2628   DCHECK_EQ(2, args.length());
   2629   Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
   2630   Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
   2631   BinaryOpIC ic(isolate);
   2632   Handle<Object> result;
   2633   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2634       isolate, result,
   2635       ic.Transition(Handle<AllocationSite>::null(), left, right));
   2636   return *result;
   2637 }
   2638 
   2639 
   2640 RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
   2641   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2642   HandleScope scope(isolate);
   2643   DCHECK_EQ(3, args.length());
   2644   Handle<AllocationSite> allocation_site =
   2645       args.at<AllocationSite>(BinaryOpWithAllocationSiteStub::kAllocationSite);
   2646   Handle<Object> left = args.at<Object>(BinaryOpWithAllocationSiteStub::kLeft);
   2647   Handle<Object> right =
   2648       args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
   2649   BinaryOpIC ic(isolate);
   2650   Handle<Object> result;
   2651   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2652       isolate, result, ic.Transition(allocation_site, left, right));
   2653   return *result;
   2654 }
   2655 
   2656 
   2657 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op,
   2658                                      Strength strength) {
   2659   CompareICStub stub(isolate, op, strength, CompareICState::UNINITIALIZED,
   2660                      CompareICState::UNINITIALIZED,
   2661                      CompareICState::UNINITIALIZED);
   2662   Code* code = NULL;
   2663   CHECK(stub.FindCodeInCache(&code));
   2664   return code;
   2665 }
   2666 
   2667 
   2668 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op,
   2669                                          Strength strength) {
   2670   CompareICStub stub(isolate, op, strength, CompareICState::UNINITIALIZED,
   2671                      CompareICState::UNINITIALIZED,
   2672                      CompareICState::UNINITIALIZED);
   2673   return stub.GetCode();
   2674 }
   2675 
   2676 
   2677 Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
   2678   HandleScope scope(isolate());
   2679   CompareICStub old_stub(target()->stub_key(), isolate());
   2680   CompareICState::State new_left =
   2681       CompareICState::NewInputState(old_stub.left(), x);
   2682   CompareICState::State new_right =
   2683       CompareICState::NewInputState(old_stub.right(), y);
   2684   CompareICState::State state = CompareICState::TargetState(
   2685       old_stub.state(), old_stub.left(), old_stub.right(), op_,
   2686       HasInlinedSmiCode(address()), x, y);
   2687   CompareICStub stub(isolate(), op_, old_stub.strength(), new_left, new_right,
   2688                      state);
   2689   if (state == CompareICState::KNOWN_RECEIVER) {
   2690     stub.set_known_map(
   2691         Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate()));
   2692   }
   2693   Handle<Code> new_target = stub.GetCode();
   2694   set_target(*new_target);
   2695 
   2696   if (FLAG_trace_ic) {
   2697     PrintF("[CompareIC in ");
   2698     JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
   2699     PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
   2700            CompareICState::GetStateName(old_stub.left()),
   2701            CompareICState::GetStateName(old_stub.right()),
   2702            CompareICState::GetStateName(old_stub.state()),
   2703            CompareICState::GetStateName(new_left),
   2704            CompareICState::GetStateName(new_right),
   2705            CompareICState::GetStateName(state), Token::Name(op_),
   2706            static_cast<void*>(*stub.GetCode()));
   2707   }
   2708 
   2709   // Activate inlined smi code.
   2710   if (old_stub.state() == CompareICState::UNINITIALIZED) {
   2711     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
   2712   }
   2713 
   2714   return *new_target;
   2715 }
   2716 
   2717 
   2718 // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
   2719 RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
   2720   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2721   HandleScope scope(isolate);
   2722   DCHECK(args.length() == 3);
   2723   CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
   2724   return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
   2725 }
   2726 
   2727 
   2728 void CompareNilIC::Clear(Address address, Code* target, Address constant_pool) {
   2729   if (IsCleared(target)) return;
   2730   ExtraICState state = target->extra_ic_state();
   2731 
   2732   CompareNilICStub stub(target->GetIsolate(), state,
   2733                         HydrogenCodeStub::UNINITIALIZED);
   2734   stub.ClearState();
   2735 
   2736   Code* code = NULL;
   2737   CHECK(stub.FindCodeInCache(&code));
   2738 
   2739   SetTargetAtAddress(address, code, constant_pool);
   2740 }
   2741 
   2742 
   2743 Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, NilValue nil,
   2744                                               Handle<Object> object) {
   2745   if (object->IsNull() || object->IsUndefined()) {
   2746     return isolate->factory()->true_value();
   2747   }
   2748   return isolate->factory()->ToBoolean(object->IsUndetectableObject());
   2749 }
   2750 
   2751 
   2752 Handle<Object> CompareNilIC::CompareNil(Handle<Object> object) {
   2753   ExtraICState extra_ic_state = target()->extra_ic_state();
   2754 
   2755   CompareNilICStub stub(isolate(), extra_ic_state);
   2756 
   2757   // Extract the current supported types from the patched IC and calculate what
   2758   // types must be supported as a result of the miss.
   2759   bool already_monomorphic = stub.IsMonomorphic();
   2760 
   2761   stub.UpdateStatus(object);
   2762 
   2763   NilValue nil = stub.nil_value();
   2764 
   2765   // Find or create the specialized stub to support the new set of types.
   2766   Handle<Code> code;
   2767   if (stub.IsMonomorphic()) {
   2768     Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL
   2769                                     ? FirstTargetMap()
   2770                                     : HeapObject::cast(*object)->map());
   2771     code = PropertyICCompiler::ComputeCompareNil(monomorphic_map, &stub);
   2772   } else {
   2773     code = stub.GetCode();
   2774   }
   2775   set_target(*code);
   2776   return DoCompareNilSlow(isolate(), nil, object);
   2777 }
   2778 
   2779 
   2780 RUNTIME_FUNCTION(Runtime_CompareNilIC_Miss) {
   2781   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2782   HandleScope scope(isolate);
   2783   Handle<Object> object = args.at<Object>(0);
   2784   CompareNilIC ic(isolate);
   2785   return *ic.CompareNil(object);
   2786 }
   2787 
   2788 
   2789 RUNTIME_FUNCTION(Runtime_Unreachable) {
   2790   UNREACHABLE();
   2791   CHECK(false);
   2792   return isolate->heap()->undefined_value();
   2793 }
   2794 
   2795 
   2796 Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
   2797   ToBooleanStub stub(isolate(), target()->extra_ic_state());
   2798   bool to_boolean_value = stub.UpdateStatus(object);
   2799   Handle<Code> code = stub.GetCode();
   2800   set_target(*code);
   2801   return isolate()->factory()->ToBoolean(to_boolean_value);
   2802 }
   2803 
   2804 
   2805 RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
   2806   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2807   DCHECK(args.length() == 1);
   2808   HandleScope scope(isolate);
   2809   Handle<Object> object = args.at<Object>(0);
   2810   ToBooleanIC ic(isolate);
   2811   return *ic.ToBoolean(object);
   2812 }
   2813 
   2814 
   2815 RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
   2816   Handle<JSObject> receiver = args.at<JSObject>(0);
   2817   Handle<JSObject> holder = args.at<JSObject>(1);
   2818   Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
   2819   Handle<Name> name = args.at<Name>(3);
   2820   Handle<Object> value = args.at<Object>(4);
   2821   HandleScope scope(isolate);
   2822 
   2823   Handle<ExecutableAccessorInfo> callback(
   2824       callback_or_cell->IsWeakCell()
   2825           ? ExecutableAccessorInfo::cast(
   2826                 WeakCell::cast(*callback_or_cell)->value())
   2827           : ExecutableAccessorInfo::cast(*callback_or_cell));
   2828 
   2829   DCHECK(callback->IsCompatibleReceiver(*receiver));
   2830 
   2831   Address setter_address = v8::ToCData<Address>(callback->setter());
   2832   v8::AccessorNameSetterCallback fun =
   2833       FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
   2834   DCHECK(fun != NULL);
   2835 
   2836   LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name));
   2837   PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
   2838                                         *holder);
   2839   custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
   2840   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2841   return *value;
   2842 }
   2843 
   2844 
   2845 /**
   2846  * Attempts to load a property with an interceptor (which must be present),
   2847  * but doesn't search the prototype chain.
   2848  *
   2849  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
   2850  * provide any value for the given name.
   2851  */
   2852 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) {
   2853   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
   2854   Handle<Name> name =
   2855       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
   2856   Handle<JSObject> receiver =
   2857       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
   2858   Handle<JSObject> holder =
   2859       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
   2860   HandleScope scope(isolate);
   2861   LookupIterator it(receiver, name, holder, LookupIterator::OWN);
   2862   bool done;
   2863   Handle<Object> result;
   2864   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2865       isolate, result, JSObject::GetPropertyWithInterceptor(&it, &done));
   2866   if (done) return *result;
   2867   return isolate->heap()->no_interceptor_result_sentinel();
   2868 }
   2869 
   2870 
   2871 /**
   2872  * Loads a property with an interceptor performing post interceptor
   2873  * lookup if interceptor failed.
   2874  */
   2875 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
   2876   HandleScope scope(isolate);
   2877   DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
   2878   Handle<Name> name =
   2879       args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
   2880   Handle<JSObject> receiver =
   2881       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
   2882   Handle<JSObject> holder =
   2883       args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
   2884 
   2885   Handle<Object> result;
   2886   LookupIterator it(receiver, name, holder);
   2887   // TODO(conradw): Investigate strong mode semantics for this.
   2888   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2889                                      JSObject::GetProperty(&it));
   2890 
   2891   if (it.IsFound()) return *result;
   2892 
   2893   // Return the undefined result if the reference error should not be thrown.
   2894   // Note that both keyed and non-keyed loads may end up here.
   2895   LoadICNexus nexus(isolate);
   2896   LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2897   if (!ic.ShouldThrowReferenceError(it.GetReceiver())) {
   2898     return isolate->heap()->undefined_value();
   2899   }
   2900 
   2901   // Throw a reference error.
   2902   THROW_NEW_ERROR_RETURN_FAILURE(
   2903       isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
   2904 }
   2905 
   2906 
   2907 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
   2908   HandleScope scope(isolate);
   2909   DCHECK(args.length() == 3);
   2910   StoreICNexus nexus(isolate);
   2911   StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
   2912   Handle<JSObject> receiver = args.at<JSObject>(0);
   2913   Handle<Name> name = args.at<Name>(1);
   2914   Handle<Object> value = args.at<Object>(2);
   2915 #ifdef DEBUG
   2916   PrototypeIterator iter(isolate, receiver,
   2917                          PrototypeIterator::START_AT_RECEIVER);
   2918   bool found = false;
   2919   for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
   2920     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
   2921     if (current->IsJSObject() &&
   2922         Handle<JSObject>::cast(current)->HasNamedInterceptor()) {
   2923       found = true;
   2924       break;
   2925     }
   2926   }
   2927   DCHECK(found);
   2928 #endif
   2929   Handle<Object> result;
   2930   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2931       isolate, result,
   2932       JSObject::SetProperty(receiver, name, value, ic.language_mode()));
   2933   return *result;
   2934 }
   2935 
   2936 
   2937 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
   2938   // TODO(verwaest): This should probably get the holder and receiver as input.
   2939   HandleScope scope(isolate);
   2940   Handle<JSObject> receiver = args.at<JSObject>(0);
   2941   DCHECK(args.smi_at(1) >= 0);
   2942   uint32_t index = args.smi_at(1);
   2943   Handle<Object> result;
   2944   // TODO(conradw): Investigate strong mode semantics for this.
   2945   LanguageMode language_mode = SLOPPY;
   2946   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2947       isolate, result,
   2948       Object::GetElement(isolate, receiver, index, language_mode));
   2949   return *result;
   2950 }
   2951 
   2952 
   2953 RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) {
   2954   TimerEventScope<TimerEventIcMiss> timer(isolate);
   2955   HandleScope scope(isolate);
   2956   Handle<Object> receiver = args.at<Object>(0);
   2957   Handle<Name> key = args.at<Name>(1);
   2958   Handle<Object> result;
   2959 
   2960   DCHECK(args.length() == 4);
   2961   Handle<Smi> slot = args.at<Smi>(2);
   2962   Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
   2963   FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
   2964   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
   2965   // LoadIC miss handler if the handler misses. Since the vector Nexus is
   2966   // set up outside the IC, handle that here.
   2967   if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
   2968     LoadICNexus nexus(vector, vector_slot);
   2969     LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2970     ic.UpdateState(receiver, key);
   2971     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2972   } else {
   2973     DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
   2974               vector->GetKind(vector_slot));
   2975     KeyedLoadICNexus nexus(vector, vector_slot);
   2976     KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
   2977     ic.UpdateState(receiver, key);
   2978     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
   2979   }
   2980 
   2981   return *result;
   2982 }
   2983 }  // namespace internal
   2984 }  // namespace v8
   2985