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