Home | History | Annotate | Download | only in ic
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/ic/ic.h"
      6 
      7 #include "src/accessors.h"
      8 #include "src/api-arguments-inl.h"
      9 #include "src/api.h"
     10 #include "src/arguments-inl.h"
     11 #include "src/ast/ast.h"
     12 #include "src/base/bits.h"
     13 #include "src/conversions.h"
     14 #include "src/execution.h"
     15 #include "src/field-type.h"
     16 #include "src/frames-inl.h"
     17 #include "src/handles-inl.h"
     18 #include "src/ic/call-optimization.h"
     19 #include "src/ic/handler-configuration-inl.h"
     20 #include "src/ic/ic-inl.h"
     21 #include "src/ic/ic-stats.h"
     22 #include "src/ic/stub-cache.h"
     23 #include "src/isolate-inl.h"
     24 #include "src/macro-assembler.h"
     25 #include "src/objects/api-callbacks.h"
     26 #include "src/objects/data-handler-inl.h"
     27 #include "src/objects/hash-table-inl.h"
     28 #include "src/objects/js-array-inl.h"
     29 #include "src/objects/module-inl.h"
     30 #include "src/prototype.h"
     31 #include "src/runtime-profiler.h"
     32 #include "src/runtime/runtime-utils.h"
     33 #include "src/runtime/runtime.h"
     34 #include "src/tracing/trace-event.h"
     35 #include "src/tracing/tracing-category-observer.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     39 
     40 char IC::TransitionMarkFromState(IC::State state) {
     41   switch (state) {
     42     case UNINITIALIZED:
     43       return '0';
     44     case PREMONOMORPHIC:
     45       return '.';
     46     case MONOMORPHIC:
     47       return '1';
     48     case RECOMPUTE_HANDLER:
     49       return '^';
     50     case POLYMORPHIC:
     51       return 'P';
     52     case MEGAMORPHIC:
     53       return 'N';
     54     case GENERIC:
     55       return 'G';
     56   }
     57   UNREACHABLE();
     58 }
     59 
     60 namespace {
     61 
     62 const char* GetModifier(KeyedAccessLoadMode mode) {
     63   if (mode == LOAD_IGNORE_OUT_OF_BOUNDS) return ".IGNORE_OOB";
     64   return "";
     65 }
     66 
     67 const char* GetModifier(KeyedAccessStoreMode mode) {
     68   switch (mode) {
     69     case STORE_NO_TRANSITION_HANDLE_COW:
     70       return ".COW";
     71     case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
     72       return ".STORE+COW";
     73     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
     74       return ".IGNORE_OOB";
     75     default:
     76       break;
     77   }
     78   DCHECK(!IsCOWHandlingStoreMode(mode));
     79   return IsGrowStoreMode(mode) ? ".GROW" : "";
     80 }
     81 
     82 }  // namespace
     83 
     84 void IC::TraceIC(const char* type, Handle<Object> name) {
     85   if (FLAG_ic_stats) {
     86     if (AddressIsDeoptimizedCode()) return;
     87     State new_state = nexus()->StateFromFeedback();
     88     TraceIC(type, name, state(), new_state);
     89   }
     90 }
     91 
     92 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
     93                  State new_state) {
     94   if (V8_LIKELY(!FLAG_ic_stats)) return;
     95 
     96   Map* map = nullptr;
     97   if (!receiver_map().is_null()) {
     98     map = *receiver_map();
     99   }
    100 
    101   const char* modifier = "";
    102   if (IsKeyedLoadIC()) {
    103     KeyedAccessLoadMode mode = nexus()->GetKeyedAccessLoadMode();
    104     modifier = GetModifier(mode);
    105   } else if (IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind())) {
    106     KeyedAccessStoreMode mode = nexus()->GetKeyedAccessStoreMode();
    107     modifier = GetModifier(mode);
    108   }
    109 
    110   bool keyed_prefix = is_keyed() && !IsStoreInArrayLiteralICKind(kind());
    111 
    112   if (!(FLAG_ic_stats &
    113         v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
    114     LOG(isolate(), ICEvent(type, keyed_prefix, map, *name,
    115                            TransitionMarkFromState(old_state),
    116                            TransitionMarkFromState(new_state), modifier,
    117                            slow_stub_reason_));
    118     return;
    119   }
    120 
    121   ICStats::instance()->Begin();
    122   ICInfo& ic_info = ICStats::instance()->Current();
    123   ic_info.type = keyed_prefix ? "Keyed" : "";
    124   ic_info.type += type;
    125 
    126   Object* maybe_function =
    127       Memory<Object*>(fp_ + JavaScriptFrameConstants::kFunctionOffset);
    128   DCHECK(maybe_function->IsJSFunction());
    129   JSFunction* function = JSFunction::cast(maybe_function);
    130   int code_offset = 0;
    131   if (function->IsInterpreted()) {
    132     code_offset = InterpretedFrame::GetBytecodeOffset(fp());
    133   } else {
    134     code_offset = static_cast<int>(pc() - function->code()->InstructionStart());
    135   }
    136   JavaScriptFrame::CollectFunctionAndOffsetForICStats(
    137       function, function->abstract_code(), code_offset);
    138 
    139   // Reserve enough space for IC transition state, the longest length is 17.
    140   ic_info.state.reserve(17);
    141   ic_info.state = "(";
    142   ic_info.state += TransitionMarkFromState(old_state);
    143   ic_info.state += "->";
    144   ic_info.state += TransitionMarkFromState(new_state);
    145   ic_info.state += modifier;
    146   ic_info.state += ")";
    147   ic_info.map = reinterpret_cast<void*>(map);
    148   if (map != nullptr) {
    149     ic_info.is_dictionary_map = map->is_dictionary_map();
    150     ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors();
    151     ic_info.instance_type = std::to_string(map->instance_type());
    152   }
    153   // TODO(lpy) Add name as key field in ICStats.
    154   ICStats::instance()->End();
    155 }
    156 
    157 IC::IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot)
    158     : isolate_(isolate),
    159       vector_set_(false),
    160       kind_(FeedbackSlotKind::kInvalid),
    161       target_maps_set_(false),
    162       slow_stub_reason_(nullptr),
    163       nexus_(vector, slot) {
    164   // To improve the performance of the (much used) IC code, we unfold a few
    165   // levels of the stack frame iteration code. This yields a ~35% speedup when
    166   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
    167   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
    168   Address* constant_pool = nullptr;
    169   if (FLAG_enable_embedded_constant_pool) {
    170     constant_pool = reinterpret_cast<Address*>(
    171         entry + ExitFrameConstants::kConstantPoolOffset);
    172   }
    173   Address* pc_address =
    174       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
    175   Address fp = Memory<Address>(entry + ExitFrameConstants::kCallerFPOffset);
    176 #ifdef DEBUG
    177   StackFrameIterator it(isolate);
    178   for (int i = 0; i < 1; i++) it.Advance();
    179   StackFrame* frame = it.frame();
    180   DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
    181 #endif
    182   // For interpreted functions, some bytecode handlers construct a
    183   // frame. We have to skip the constructed frame to find the interpreted
    184   // function's frame. Check if the there is an additional frame, and if there
    185   // is skip this frame. However, the pc should not be updated. The call to
    186   // ICs happen from bytecode handlers.
    187   intptr_t frame_marker =
    188       Memory<intptr_t>(fp + TypedFrameConstants::kFrameTypeOffset);
    189   if (frame_marker == StackFrame::TypeToMarker(StackFrame::STUB)) {
    190     fp = Memory<Address>(fp + TypedFrameConstants::kCallerFPOffset);
    191   }
    192   fp_ = fp;
    193   if (FLAG_enable_embedded_constant_pool) {
    194     constant_pool_address_ = constant_pool;
    195   }
    196   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
    197   kind_ = nexus_.kind();
    198   state_ = nexus_.StateFromFeedback();
    199   old_state_ = state_;
    200 }
    201 
    202 JSFunction* IC::GetHostFunction() const {
    203   // Compute the JavaScript frame for the frame pointer of this IC
    204   // structure. We need this to be able to find the function
    205   // corresponding to the frame.
    206   StackFrameIterator it(isolate());
    207   while (it.frame()->fp() != this->fp()) it.Advance();
    208   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
    209   // Find the function on the stack and both the active code for the
    210   // function and the original code.
    211   return frame->function();
    212 }
    213 
    214 static void LookupForRead(Isolate* isolate, LookupIterator* it) {
    215   for (; it->IsFound(); it->Next()) {
    216     switch (it->state()) {
    217       case LookupIterator::NOT_FOUND:
    218       case LookupIterator::TRANSITION:
    219         UNREACHABLE();
    220       case LookupIterator::JSPROXY:
    221         return;
    222       case LookupIterator::INTERCEPTOR: {
    223         // If there is a getter, return; otherwise loop to perform the lookup.
    224         Handle<JSObject> holder = it->GetHolder<JSObject>();
    225         if (!holder->GetNamedInterceptor()->getter()->IsUndefined(isolate)) {
    226           return;
    227         }
    228         break;
    229       }
    230       case LookupIterator::ACCESS_CHECK:
    231         // ICs know how to perform access checks on global proxies.
    232         if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
    233           break;
    234         }
    235         return;
    236       case LookupIterator::ACCESSOR:
    237       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    238       case LookupIterator::DATA:
    239         return;
    240     }
    241   }
    242 }
    243 
    244 bool IC::ShouldRecomputeHandler(Handle<String> name) {
    245   if (!RecomputeHandlerForName(name)) return false;
    246 
    247   // This is a contextual access, always just update the handler and stay
    248   // monomorphic.
    249   if (IsGlobalIC()) return true;
    250 
    251   maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
    252 
    253   // The current map wasn't handled yet. There's no reason to stay monomorphic,
    254   // *unless* we're moving from a deprecated map to its replacement, or
    255   // to a more general elements kind.
    256   // TODO(verwaest): Check if the current map is actually what the old map
    257   // would transition to.
    258   if (maybe_handler_.is_null()) {
    259     if (!receiver_map()->IsJSObjectMap()) return false;
    260     Map* first_map = FirstTargetMap();
    261     if (first_map == nullptr) return false;
    262     Handle<Map> old_map(first_map, isolate());
    263     if (old_map->is_deprecated()) return true;
    264     return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
    265                                                receiver_map()->elements_kind());
    266   }
    267 
    268   return true;
    269 }
    270 
    271 bool IC::RecomputeHandlerForName(Handle<Object> name) {
    272   if (is_keyed()) {
    273     // Determine whether the failure is due to a name failure.
    274     if (!name->IsName()) return false;
    275     Name* stub_name = nexus()->FindFirstName();
    276     if (*name != stub_name) return false;
    277   }
    278 
    279   return true;
    280 }
    281 
    282 
    283 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
    284   update_receiver_map(receiver);
    285   if (!name->IsString()) return;
    286   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
    287   if (receiver->IsNullOrUndefined(isolate())) return;
    288 
    289   // Remove the target from the code cache if it became invalid
    290   // because of changes in the prototype chain to avoid hitting it
    291   // again.
    292   if (ShouldRecomputeHandler(Handle<String>::cast(name))) {
    293     MarkRecomputeHandler(name);
    294   }
    295 }
    296 
    297 
    298 MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
    299                                   Handle<Object> object, Handle<Object> key) {
    300   HandleScope scope(isolate());
    301   THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
    302 }
    303 
    304 
    305 MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
    306   HandleScope scope(isolate());
    307   THROW_NEW_ERROR(
    308       isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
    309 }
    310 
    311 // static
    312 void IC::OnFeedbackChanged(Isolate* isolate, FeedbackNexus* nexus,
    313                            JSFunction* host_function, const char* reason) {
    314   FeedbackVector* vector = nexus->vector();
    315   FeedbackSlot slot = nexus->slot();
    316   OnFeedbackChanged(isolate, vector, slot, host_function, reason);
    317 }
    318 
    319 // static
    320 void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
    321                            FeedbackSlot slot, JSFunction* host_function,
    322                            const char* reason) {
    323   if (FLAG_trace_opt_verbose) {
    324     // TODO(leszeks): The host function is only needed for this print, we could
    325     // remove it as a parameter if we're of with removing this trace (or only
    326     // tracing the feedback vector, not the function name).
    327     if (vector->profiler_ticks() != 0) {
    328       PrintF("[resetting ticks for ");
    329       host_function->ShortPrint();
    330       PrintF(" due from %d due to IC change: %s]\n", vector->profiler_ticks(),
    331              reason);
    332     }
    333   }
    334   vector->set_profiler_ticks(0);
    335 
    336 #ifdef V8_TRACE_FEEDBACK_UPDATES
    337   if (FLAG_trace_feedback_updates) {
    338     int slot_count = vector->metadata()->slot_count();
    339 
    340     StdoutStream os;
    341     if (slot.IsInvalid()) {
    342       os << "[Feedback slots in ";
    343     } else {
    344       os << "[Feedback slot " << slot.ToInt() << "/" << slot_count << " in ";
    345     }
    346     vector->shared_function_info()->ShortPrint(os);
    347     if (slot.IsInvalid()) {
    348       os << " updated - ";
    349     } else {
    350       os << " updated to ";
    351       vector->FeedbackSlotPrint(os, slot);
    352       os << " - ";
    353     }
    354     os << reason << "]" << std::endl;
    355   }
    356 #endif
    357 
    358   isolate->runtime_profiler()->NotifyICChanged();
    359   // TODO(2029): When an optimized function is patched, it would
    360   // be nice to propagate the corresponding type information to its
    361   // unoptimized version for the benefit of later inlining.
    362 }
    363 
    364 static bool MigrateDeprecated(Handle<Object> object) {
    365   if (!object->IsJSObject()) return false;
    366   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    367   if (!receiver->map()->is_deprecated()) return false;
    368   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
    369   return true;
    370 }
    371 
    372 bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
    373   DCHECK_EQ(MEGAMORPHIC, new_state);
    374   DCHECK_IMPLIES(!is_keyed(), key->IsName());
    375   // Even though we don't change the feedback data, we still want to reset the
    376   // profiler ticks. Real-world observations suggest that optimizing these
    377   // functions doesn't improve performance.
    378   bool changed =
    379       nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
    380   vector_set_ = true;
    381   OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Megamorphic");
    382   return changed;
    383 }
    384 
    385 void IC::ConfigureVectorState(Handle<Map> map) {
    386   nexus()->ConfigurePremonomorphic(map);
    387   vector_set_ = true;
    388   OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Premonomorphic");
    389 }
    390 
    391 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
    392                               Handle<Object> handler) {
    393   ConfigureVectorState(name, map, MaybeObjectHandle(handler));
    394 }
    395 
    396 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
    397                               const MaybeObjectHandle& handler) {
    398   if (IsGlobalIC()) {
    399     nexus()->ConfigureHandlerMode(handler);
    400   } else {
    401     // Non-keyed ICs don't track the name explicitly.
    402     if (!is_keyed()) name = Handle<Name>::null();
    403     nexus()->ConfigureMonomorphic(name, map, handler);
    404   }
    405 
    406   vector_set_ = true;
    407   OnFeedbackChanged(isolate(), nexus(), GetHostFunction(),
    408                     IsLoadGlobalIC() ? "LoadGlobal" : "Monomorphic");
    409 }
    410 
    411 void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
    412                               MaybeObjectHandles* handlers) {
    413   DCHECK(!IsGlobalIC());
    414   // Non-keyed ICs don't track the name explicitly.
    415   if (!is_keyed()) name = Handle<Name>::null();
    416   nexus()->ConfigurePolymorphic(name, maps, handlers);
    417 
    418   vector_set_ = true;
    419   OnFeedbackChanged(isolate(), nexus(), GetHostFunction(), "Polymorphic");
    420 }
    421 
    422 MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
    423   // If the object is undefined or null it's illegal to try to get any
    424   // of its properties; throw a TypeError in that case.
    425   if (object->IsNullOrUndefined(isolate())) {
    426     if (FLAG_use_ic && state() != PREMONOMORPHIC) {
    427       // Ensure the IC state progresses.
    428       TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
    429       update_receiver_map(object);
    430       PatchCache(name, slow_stub());
    431       TraceIC("LoadIC", name);
    432     }
    433 
    434     if (*name == ReadOnlyRoots(isolate()).iterator_symbol()) {
    435       return Runtime::ThrowIteratorError(isolate(), object);
    436     }
    437     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
    438   }
    439 
    440   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
    441 
    442   if (state() != UNINITIALIZED) {
    443     JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
    444     update_receiver_map(object);
    445   }
    446   // Named lookup in the object.
    447   LookupIterator it(isolate(), object, name);
    448   LookupForRead(isolate(), &it);
    449 
    450   if (name->IsPrivate()) {
    451     if (name->IsPrivateField() && !it.IsFound()) {
    452       return TypeError(MessageTemplate::kInvalidPrivateFieldAccess, object,
    453                        name);
    454     }
    455 
    456     // IC handling of private symbols/fields lookup on JSProxy is not
    457     // supported.
    458     if (object->IsJSProxy()) {
    459       use_ic = false;
    460     }
    461   }
    462 
    463   if (it.IsFound() || !ShouldThrowReferenceError()) {
    464     // Update inline cache and stub cache.
    465     if (use_ic) UpdateCaches(&it);
    466 
    467     // Get the property.
    468     Handle<Object> result;
    469 
    470     ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
    471                                Object);
    472     if (it.IsFound()) {
    473       return result;
    474     } else if (!ShouldThrowReferenceError()) {
    475       LOG(isolate(), SuspectReadEvent(*name, *object));
    476       return result;
    477     }
    478   }
    479   return ReferenceError(name);
    480 }
    481 
    482 MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
    483   Handle<JSGlobalObject> global = isolate()->global_object();
    484 
    485   if (name->IsString()) {
    486     // Look up in script context table.
    487     Handle<String> str_name = Handle<String>::cast(name);
    488     Handle<ScriptContextTable> script_contexts(
    489         global->native_context()->script_context_table(), isolate());
    490 
    491     ScriptContextTable::LookupResult lookup_result;
    492     if (ScriptContextTable::Lookup(isolate(), script_contexts, str_name,
    493                                    &lookup_result)) {
    494       Handle<Object> result = FixedArray::get(
    495           *ScriptContextTable::GetContext(isolate(), script_contexts,
    496                                           lookup_result.context_index),
    497           lookup_result.slot_index, isolate());
    498       if (result->IsTheHole(isolate())) {
    499         // Do not install stubs and stay pre-monomorphic for
    500         // uninitialized accesses.
    501         return ReferenceError(name);
    502       }
    503 
    504       if (FLAG_use_ic) {
    505         if (nexus()->ConfigureLexicalVarMode(lookup_result.context_index,
    506                                              lookup_result.slot_index)) {
    507           TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_LoadScriptContextField);
    508         } else {
    509           // Given combination of indices can't be encoded, so use slow stub.
    510           TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_SlowStub);
    511           PatchCache(name, slow_stub());
    512         }
    513         TraceIC("LoadGlobalIC", name);
    514       }
    515       return result;
    516     }
    517   }
    518   return LoadIC::Load(global, name);
    519 }
    520 
    521 static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
    522                                        Handle<Map> new_receiver_map) {
    523   DCHECK(!new_receiver_map.is_null());
    524   for (Handle<Map> map : *receiver_maps) {
    525     if (!map.is_null() && map.is_identical_to(new_receiver_map)) {
    526       return false;
    527     }
    528   }
    529   receiver_maps->push_back(new_receiver_map);
    530   return true;
    531 }
    532 
    533 bool IC::UpdatePolymorphicIC(Handle<Name> name,
    534                              const MaybeObjectHandle& handler) {
    535   DCHECK(IsHandler(*handler));
    536   if (is_keyed() && state() != RECOMPUTE_HANDLER) {
    537     if (nexus()->FindFirstName() != *name) return false;
    538   }
    539   Handle<Map> map = receiver_map();
    540   MapHandles maps;
    541   MaybeObjectHandles handlers;
    542 
    543   TargetMaps(&maps);
    544   int number_of_maps = static_cast<int>(maps.size());
    545   int deprecated_maps = 0;
    546   int handler_to_overwrite = -1;
    547   if (!nexus()->FindHandlers(&handlers, number_of_maps)) return false;
    548 
    549   for (int i = 0; i < number_of_maps; i++) {
    550     Handle<Map> current_map = maps.at(i);
    551     if (current_map->is_deprecated()) {
    552       // Filter out deprecated maps to ensure their instances get migrated.
    553       ++deprecated_maps;
    554     } else if (map.is_identical_to(current_map)) {
    555       // If both map and handler stayed the same (and the name is also the
    556       // same as checked above, for keyed accesses), we're not progressing
    557       // in the lattice and need to go MEGAMORPHIC instead. There's one
    558       // exception to this rule, which is when we're in RECOMPUTE_HANDLER
    559       // state, there we allow to migrate to a new handler.
    560       if (handler.is_identical_to(handlers[i]) &&
    561           state() != RECOMPUTE_HANDLER) {
    562         return false;
    563       }
    564       // If the receiver type is already in the polymorphic IC, this indicates
    565       // there was a prototoype chain failure. In that case, just overwrite the
    566       // handler.
    567       handler_to_overwrite = i;
    568     } else if (handler_to_overwrite == -1 &&
    569                IsTransitionOfMonomorphicTarget(*current_map, *map)) {
    570       handler_to_overwrite = i;
    571     }
    572   }
    573 
    574   int number_of_valid_maps =
    575       number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
    576 
    577   if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false;
    578   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
    579     return false;
    580   }
    581 
    582   number_of_valid_maps++;
    583   if (number_of_valid_maps == 1) {
    584     ConfigureVectorState(name, receiver_map(), handler);
    585   } else {
    586     if (is_keyed() && nexus()->FindFirstName() != *name) return false;
    587     if (handler_to_overwrite >= 0) {
    588       handlers[handler_to_overwrite] = handler;
    589       if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
    590         maps[handler_to_overwrite] = map;
    591       }
    592     } else {
    593       maps.push_back(map);
    594       handlers.push_back(handler);
    595     }
    596 
    597     ConfigureVectorState(name, maps, &handlers);
    598   }
    599 
    600   return true;
    601 }
    602 
    603 void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
    604                              Handle<Name> name) {
    605   DCHECK(IsHandler(*handler));
    606   ConfigureVectorState(name, receiver_map(), handler);
    607 }
    608 
    609 
    610 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
    611   MapHandles maps;
    612   MaybeObjectHandles handlers;
    613   TargetMaps(&maps);
    614   if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return;
    615   for (int i = 0; i < static_cast<int>(maps.size()); i++) {
    616     UpdateMegamorphicCache(maps.at(i), name, handlers.at(i));
    617   }
    618 }
    619 
    620 
    621 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
    622   if (source_map == nullptr) return true;
    623   if (target_map == nullptr) return false;
    624   if (source_map->is_abandoned_prototype_map()) return false;
    625   ElementsKind target_elements_kind = target_map->elements_kind();
    626   bool more_general_transition = IsMoreGeneralElementsKindTransition(
    627       source_map->elements_kind(), target_elements_kind);
    628   Map* transitioned_map = nullptr;
    629   if (more_general_transition) {
    630     MapHandles map_list;
    631     map_list.push_back(handle(target_map, isolate_));
    632     transitioned_map =
    633         source_map->FindElementsKindTransitionedMap(isolate(), map_list);
    634   }
    635   return transitioned_map == target_map;
    636 }
    637 
    638 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
    639   PatchCache(name, MaybeObjectHandle(handler));
    640 }
    641 
    642 void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) {
    643   DCHECK(IsHandler(*handler));
    644   // Currently only load and store ICs support non-code handlers.
    645   DCHECK(IsAnyLoad() || IsAnyStore());
    646   switch (state()) {
    647     case UNINITIALIZED:
    648     case PREMONOMORPHIC:
    649       UpdateMonomorphicIC(handler, name);
    650       break;
    651     case RECOMPUTE_HANDLER:
    652     case MONOMORPHIC:
    653       if (IsGlobalIC()) {
    654         UpdateMonomorphicIC(handler, name);
    655         break;
    656       }
    657       V8_FALLTHROUGH;
    658     case POLYMORPHIC:
    659       if (UpdatePolymorphicIC(name, handler)) break;
    660       if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
    661         CopyICToMegamorphicCache(name);
    662       }
    663       ConfigureVectorState(MEGAMORPHIC, name);
    664       V8_FALLTHROUGH;
    665     case MEGAMORPHIC:
    666       UpdateMegamorphicCache(receiver_map(), name, handler);
    667       // Indicate that we've handled this case.
    668       vector_set_ = true;
    669       break;
    670     case GENERIC:
    671       UNREACHABLE();
    672       break;
    673   }
    674 }
    675 
    676 void LoadIC::UpdateCaches(LookupIterator* lookup) {
    677   if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
    678     // This is the first time we execute this inline cache. Set the target to
    679     // the pre monomorphic stub to delay setting the monomorphic state.
    680     TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
    681     ConfigureVectorState(receiver_map());
    682     TraceIC("LoadIC", lookup->name());
    683     return;
    684   }
    685 
    686   Handle<Object> code;
    687   if (lookup->state() == LookupIterator::ACCESS_CHECK) {
    688     code = slow_stub();
    689   } else if (!lookup->IsFound()) {
    690     TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
    691     Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
    692     code = LoadHandler::LoadFullChain(
    693         isolate(), receiver_map(),
    694         MaybeObjectHandle(isolate()->factory()->null_value()), smi_handler);
    695   } else {
    696     if (IsLoadGlobalIC()) {
    697       if (lookup->TryLookupCachedProperty()) {
    698         DCHECK_EQ(LookupIterator::DATA, lookup->state());
    699       }
    700       if (lookup->state() == LookupIterator::DATA &&
    701           lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
    702         DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
    703         // Now update the cell in the feedback vector.
    704         nexus()->ConfigurePropertyCellMode(lookup->GetPropertyCell());
    705         TraceIC("LoadGlobalIC", lookup->name());
    706         return;
    707       }
    708     }
    709     code = ComputeHandler(lookup);
    710   }
    711 
    712   PatchCache(lookup->name(), code);
    713   TraceIC("LoadIC", lookup->name());
    714 }
    715 
    716 StubCache* IC::stub_cache() {
    717   if (IsAnyLoad()) {
    718     return isolate()->load_stub_cache();
    719   } else {
    720     DCHECK(IsAnyStore());
    721     return isolate()->store_stub_cache();
    722   }
    723 }
    724 
    725 void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
    726                                 const MaybeObjectHandle& handler) {
    727   stub_cache()->Set(*name, *map, *handler);
    728 }
    729 
    730 void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
    731   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
    732   if (V8_LIKELY(!FLAG_runtime_stats)) return;
    733   if (IsAnyLoad()) {
    734     TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor);
    735   } else {
    736     DCHECK(IsAnyStore());
    737     TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor);
    738   }
    739 }
    740 
    741 Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
    742   Handle<Object> receiver = lookup->GetReceiver();
    743   ReadOnlyRoots roots(isolate());
    744   if (receiver->IsString() && *lookup->name() == roots.length_string()) {
    745     TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
    746     return BUILTIN_CODE(isolate(), LoadIC_StringLength);
    747   }
    748 
    749   if (receiver->IsStringWrapper() && *lookup->name() == roots.length_string()) {
    750     TRACE_HANDLER_STATS(isolate(), LoadIC_StringWrapperLength);
    751     return BUILTIN_CODE(isolate(), LoadIC_StringWrapperLength);
    752   }
    753 
    754   // Use specialized code for getting prototype of functions.
    755   if (receiver->IsJSFunction() && *lookup->name() == roots.prototype_string() &&
    756       !JSFunction::cast(*receiver)->PrototypeRequiresRuntimeLookup()) {
    757     Handle<Code> stub;
    758     TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
    759     return BUILTIN_CODE(isolate(), LoadIC_FunctionPrototype);
    760   }
    761 
    762   Handle<Map> map = receiver_map();
    763   Handle<JSObject> holder;
    764   bool receiver_is_holder;
    765   if (lookup->state() != LookupIterator::JSPROXY) {
    766     holder = lookup->GetHolder<JSObject>();
    767     receiver_is_holder = receiver.is_identical_to(holder);
    768   }
    769 
    770   switch (lookup->state()) {
    771     case LookupIterator::INTERCEPTOR: {
    772       Handle<Smi> smi_handler = LoadHandler::LoadInterceptor(isolate());
    773 
    774       if (holder->GetNamedInterceptor()->non_masking()) {
    775         MaybeObjectHandle holder_ref(isolate()->factory()->null_value());
    776         if (!receiver_is_holder || IsLoadGlobalIC()) {
    777           holder_ref = MaybeObjectHandle::Weak(holder);
    778         }
    779         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonMaskingInterceptorDH);
    780         return LoadHandler::LoadFullChain(isolate(), map, holder_ref,
    781                                           smi_handler);
    782       }
    783 
    784       if (receiver_is_holder) {
    785         DCHECK(map->has_named_interceptor());
    786         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorDH);
    787         return smi_handler;
    788       }
    789 
    790       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorFromPrototypeDH);
    791       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
    792                                             smi_handler);
    793     }
    794 
    795     case LookupIterator::ACCESSOR: {
    796       // Use simple field loads for some well-known callback properties.
    797       // The method will only return true for absolute truths based on the
    798       // receiver maps.
    799       FieldIndex index;
    800       if (Accessors::IsJSObjectFieldAccessor(isolate(), map, lookup->name(),
    801                                              &index)) {
    802         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
    803         return LoadHandler::LoadField(isolate(), index);
    804       }
    805       if (holder->IsJSModuleNamespace()) {
    806         Handle<ObjectHashTable> exports(
    807             Handle<JSModuleNamespace>::cast(holder)->module()->exports(),
    808             isolate());
    809         int entry = exports->FindEntry(roots, lookup->name(),
    810                                        Smi::ToInt(lookup->name()->GetHash()));
    811         // We found the accessor, so the entry must exist.
    812         DCHECK_NE(entry, ObjectHashTable::kNotFound);
    813         int index = ObjectHashTable::EntryToValueIndex(entry);
    814         return LoadHandler::LoadModuleExport(isolate(), index);
    815       }
    816 
    817       Handle<Object> accessors = lookup->GetAccessors();
    818       if (accessors->IsAccessorPair()) {
    819         if (lookup->TryLookupCachedProperty()) {
    820           DCHECK_EQ(LookupIterator::DATA, lookup->state());
    821           return ComputeHandler(lookup);
    822         }
    823 
    824         Handle<Object> getter(AccessorPair::cast(*accessors)->getter(),
    825                               isolate());
    826         if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
    827           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    828           return slow_stub();
    829         }
    830 
    831         if (getter->IsFunctionTemplateInfo() &&
    832             FunctionTemplateInfo::cast(*getter)->BreakAtEntry()) {
    833           // Do not install an IC if the api function has a breakpoint.
    834           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    835           return slow_stub();
    836         }
    837 
    838         Handle<Smi> smi_handler;
    839 
    840         CallOptimization call_optimization(isolate(), getter);
    841         if (call_optimization.is_simple_api_call()) {
    842           if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
    843               !holder->HasFastProperties()) {
    844             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    845             return slow_stub();
    846           }
    847 
    848           CallOptimization::HolderLookup holder_lookup;
    849           call_optimization.LookupHolderOfExpectedType(map, &holder_lookup);
    850 
    851           smi_handler = LoadHandler::LoadApiGetter(
    852               isolate(), holder_lookup == CallOptimization::kHolderIsReceiver);
    853 
    854           Handle<Context> context(
    855               call_optimization.GetAccessorContext(holder->map()), isolate());
    856 
    857           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
    858           return LoadHandler::LoadFromPrototype(
    859               isolate(), map, holder, smi_handler,
    860               MaybeObjectHandle::Weak(call_optimization.api_call_info()),
    861               MaybeObjectHandle::Weak(context));
    862         }
    863 
    864         if (holder->HasFastProperties()) {
    865           smi_handler =
    866               LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
    867 
    868           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
    869           if (receiver_is_holder) return smi_handler;
    870           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorFromPrototypeDH);
    871         } else if (holder->IsJSGlobalObject()) {
    872           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
    873           smi_handler = LoadHandler::LoadGlobal(isolate());
    874           return LoadHandler::LoadFromPrototype(
    875               isolate(), map, holder, smi_handler,
    876               MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
    877         } else {
    878           smi_handler = LoadHandler::LoadNormal(isolate());
    879 
    880           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
    881           if (receiver_is_holder) return smi_handler;
    882           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
    883         }
    884 
    885         return LoadHandler::LoadFromPrototype(isolate(), map, holder,
    886                                               smi_handler);
    887       }
    888 
    889       Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    890 
    891       if (v8::ToCData<Address>(info->getter()) == kNullAddress ||
    892           !AccessorInfo::IsCompatibleReceiverMap(info, map) ||
    893           !holder->HasFastProperties() ||
    894           (info->is_sloppy() && !receiver->IsJSReceiver())) {
    895         TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    896         return slow_stub();
    897       }
    898 
    899       Handle<Smi> smi_handler = LoadHandler::LoadNativeDataProperty(
    900           isolate(), lookup->GetAccessorIndex());
    901       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNativeDataPropertyDH);
    902       if (receiver_is_holder) return smi_handler;
    903       TRACE_HANDLER_STATS(isolate(),
    904                           LoadIC_LoadNativeDataPropertyFromPrototypeDH);
    905       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
    906                                             smi_handler);
    907     }
    908 
    909     case LookupIterator::DATA: {
    910       DCHECK_EQ(kData, lookup->property_details().kind());
    911       Handle<Smi> smi_handler;
    912       if (lookup->is_dictionary_holder()) {
    913         if (holder->IsJSGlobalObject()) {
    914           // TODO(verwaest): Also supporting the global object as receiver is a
    915           // workaround for code that leaks the global object.
    916           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalDH);
    917           smi_handler = LoadHandler::LoadGlobal(isolate());
    918           return LoadHandler::LoadFromPrototype(
    919               isolate(), map, holder, smi_handler,
    920               MaybeObjectHandle::Weak(lookup->GetPropertyCell()));
    921         }
    922 
    923         smi_handler = LoadHandler::LoadNormal(isolate());
    924         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
    925         if (receiver_is_holder) return smi_handler;
    926         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
    927 
    928       } else if (lookup->property_details().location() == kField) {
    929         FieldIndex field = lookup->GetFieldIndex();
    930         smi_handler = LoadHandler::LoadField(isolate(), field);
    931         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
    932         if (receiver_is_holder) return smi_handler;
    933         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
    934       } else {
    935         DCHECK_EQ(kDescriptor, lookup->property_details().location());
    936         smi_handler =
    937             LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
    938         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
    939         if (receiver_is_holder) return smi_handler;
    940         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
    941       }
    942       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
    943                                             smi_handler);
    944     }
    945     case LookupIterator::INTEGER_INDEXED_EXOTIC:
    946       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadIntegerIndexedExoticDH);
    947       return LoadHandler::LoadNonExistent(isolate());
    948     case LookupIterator::JSPROXY: {
    949       Handle<JSProxy> holder_proxy = lookup->GetHolder<JSProxy>();
    950       bool receiver_is_holder_proxy = receiver.is_identical_to(holder_proxy);
    951       Handle<Smi> smi_handler = LoadHandler::LoadProxy(isolate());
    952       if (receiver_is_holder_proxy) {
    953         return smi_handler;
    954       }
    955       return LoadHandler::LoadFromPrototype(isolate(), map, holder_proxy,
    956                                             smi_handler);
    957     }
    958     case LookupIterator::ACCESS_CHECK:
    959     case LookupIterator::NOT_FOUND:
    960     case LookupIterator::TRANSITION:
    961       UNREACHABLE();
    962   }
    963 
    964   return Handle<Code>::null();
    965 }
    966 
    967 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
    968   // This helper implements a few common fast cases for converting
    969   // non-smi keys of keyed loads/stores to a smi or a string.
    970   if (key->IsHeapNumber()) {
    971     double value = Handle<HeapNumber>::cast(key)->value();
    972     if (std::isnan(value)) {
    973       key = isolate->factory()->NaN_string();
    974     } else {
    975       // Check bounds first to avoid undefined behavior in the conversion
    976       // to int.
    977       if (value <= Smi::kMaxValue && value >= Smi::kMinValue) {
    978         int int_value = FastD2I(value);
    979         if (value == int_value) {
    980           key = handle(Smi::FromInt(int_value), isolate);
    981         }
    982       }
    983     }
    984   } else if (key->IsString()) {
    985     key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
    986   }
    987   return key;
    988 }
    989 
    990 bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) {
    991   const MaybeObjectHandle& handler = nexus()->FindHandlerForMap(receiver_map);
    992   if (handler.is_null()) return false;
    993   return LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD;
    994 }
    995 
    996 void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
    997                                     KeyedAccessLoadMode load_mode) {
    998   Handle<Map> receiver_map(receiver->map(), isolate());
    999   DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE);  // Checked by caller.
   1000   MapHandles target_receiver_maps;
   1001   TargetMaps(&target_receiver_maps);
   1002 
   1003   if (target_receiver_maps.empty()) {
   1004     Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
   1005     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
   1006   }
   1007 
   1008   for (Handle<Map> map : target_receiver_maps) {
   1009     if (map.is_null()) continue;
   1010     if (map->instance_type() == JS_VALUE_TYPE) {
   1011       set_slow_stub_reason("JSValue");
   1012       return;
   1013     }
   1014     if (map->instance_type() == JS_PROXY_TYPE) {
   1015       set_slow_stub_reason("JSProxy");
   1016       return;
   1017     }
   1018   }
   1019 
   1020   // The first time a receiver is seen that is a transitioned version of the
   1021   // previous monomorphic receiver type, assume the new ElementsKind is the
   1022   // monomorphic type. This benefits global arrays that only transition
   1023   // once, and all call sites accessing them are faster if they remain
   1024   // monomorphic. If this optimistic assumption is not true, the IC will
   1025   // miss again and it will become polymorphic and support both the
   1026   // untransitioned and transitioned maps.
   1027   if (state() == MONOMORPHIC && !receiver->IsString() &&
   1028       !receiver->IsJSProxy() &&
   1029       IsMoreGeneralElementsKindTransition(
   1030           target_receiver_maps.at(0)->elements_kind(),
   1031           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
   1032     Handle<Object> handler = LoadElementHandler(receiver_map, load_mode);
   1033     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
   1034   }
   1035 
   1036   DCHECK(state() != GENERIC);
   1037 
   1038   // Determine the list of receiver maps that this call site has seen,
   1039   // adding the map that was just encountered.
   1040   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
   1041     // If the {receiver_map} previously had a handler that didn't handle
   1042     // out-of-bounds access, but can generally handle it, we can just go
   1043     // on and update the handler appropriately below.
   1044     if (load_mode != LOAD_IGNORE_OUT_OF_BOUNDS ||
   1045         !CanChangeToAllowOutOfBounds(receiver_map)) {
   1046       // If the miss wasn't due to an unseen map, a polymorphic stub
   1047       // won't help, use the generic stub.
   1048       set_slow_stub_reason("same map added twice");
   1049       return;
   1050     }
   1051   }
   1052 
   1053   // If the maximum number of receiver maps has been exceeded, use the generic
   1054   // version of the IC.
   1055   if (target_receiver_maps.size() > kMaxKeyedPolymorphism) {
   1056     set_slow_stub_reason("max polymorph exceeded");
   1057     return;
   1058   }
   1059 
   1060   MaybeObjectHandles handlers;
   1061   handlers.reserve(target_receiver_maps.size());
   1062   LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers, load_mode);
   1063   DCHECK_LE(1, target_receiver_maps.size());
   1064   if (target_receiver_maps.size() == 1) {
   1065     ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
   1066   } else {
   1067     ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
   1068   }
   1069 }
   1070 
   1071 Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
   1072                                                KeyedAccessLoadMode load_mode) {
   1073   if (receiver_map->has_indexed_interceptor() &&
   1074       !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
   1075           isolate()) &&
   1076       !receiver_map->GetIndexedInterceptor()->non_masking()) {
   1077     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
   1078     return LoadIndexedInterceptorStub(isolate()).GetCode();
   1079   }
   1080   InstanceType instance_type = receiver_map->instance_type();
   1081   if (instance_type < FIRST_NONSTRING_TYPE) {
   1082     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringDH);
   1083     return LoadHandler::LoadIndexedString(isolate(), load_mode);
   1084   }
   1085   if (instance_type < FIRST_JS_RECEIVER_TYPE) {
   1086     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
   1087     return BUILTIN_CODE(isolate(), KeyedLoadIC_Slow);
   1088   }
   1089   if (instance_type == JS_PROXY_TYPE) {
   1090     return LoadHandler::LoadProxy(isolate());
   1091   }
   1092 
   1093   ElementsKind elements_kind = receiver_map->elements_kind();
   1094   if (IsSloppyArgumentsElementsKind(elements_kind)) {
   1095     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
   1096     return KeyedLoadSloppyArgumentsStub(isolate()).GetCode();
   1097   }
   1098   bool is_js_array = instance_type == JS_ARRAY_TYPE;
   1099   if (elements_kind == DICTIONARY_ELEMENTS) {
   1100     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
   1101     return LoadHandler::LoadElement(isolate(), elements_kind, false,
   1102                                     is_js_array, load_mode);
   1103   }
   1104   DCHECK(IsFastElementsKind(elements_kind) ||
   1105          IsFixedTypedArrayElementsKind(elements_kind));
   1106   // TODO(jkummerow): Use IsHoleyOrDictionaryElementsKind(elements_kind).
   1107   bool convert_hole_to_undefined =
   1108       is_js_array && elements_kind == HOLEY_ELEMENTS &&
   1109       *receiver_map ==
   1110           isolate()->raw_native_context()->GetInitialJSArrayMap(elements_kind);
   1111   TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
   1112   return LoadHandler::LoadElement(isolate(), elements_kind,
   1113                                   convert_hole_to_undefined, is_js_array,
   1114                                   load_mode);
   1115 }
   1116 
   1117 void KeyedLoadIC::LoadElementPolymorphicHandlers(
   1118     MapHandles* receiver_maps, MaybeObjectHandles* handlers,
   1119     KeyedAccessLoadMode load_mode) {
   1120   // Filter out deprecated maps to ensure their instances get migrated.
   1121   receiver_maps->erase(
   1122       std::remove_if(
   1123           receiver_maps->begin(), receiver_maps->end(),
   1124           [](const Handle<Map>& map) { return map->is_deprecated(); }),
   1125       receiver_maps->end());
   1126 
   1127   for (Handle<Map> receiver_map : *receiver_maps) {
   1128     // Mark all stable receiver maps that have elements kind transition map
   1129     // among receiver_maps as unstable because the optimizing compilers may
   1130     // generate an elements kind transition for this kind of receivers.
   1131     if (receiver_map->is_stable()) {
   1132       Map* tmap = receiver_map->FindElementsKindTransitionedMap(isolate(),
   1133                                                                 *receiver_maps);
   1134       if (tmap != nullptr) {
   1135         receiver_map->NotifyLeafMapLayoutChange(isolate());
   1136       }
   1137     }
   1138     handlers->push_back(
   1139         MaybeObjectHandle(LoadElementHandler(receiver_map, load_mode)));
   1140   }
   1141 }
   1142 
   1143 namespace {
   1144 
   1145 bool ConvertKeyToIndex(Handle<Object> receiver, Handle<Object> key,
   1146                        uint32_t* index) {
   1147   if (!FLAG_use_ic) return false;
   1148   if (receiver->IsAccessCheckNeeded() || receiver->IsJSValue()) return false;
   1149 
   1150   // For regular JSReceiver or String receivers, the {key} must be a positive
   1151   // array index.
   1152   if (receiver->IsJSReceiver() || receiver->IsString()) {
   1153     if (key->ToArrayIndex(index)) return true;
   1154   }
   1155   // For JSTypedArray receivers, we can also support negative keys, which we
   1156   // just map into the [2**31, 2**32 - 1] range via a bit_cast. This is valid
   1157   // because JSTypedArray::length is always a Smi, so such keys will always
   1158   // be detected as OOB.
   1159   if (receiver->IsJSTypedArray()) {
   1160     int32_t signed_index;
   1161     if (key->ToInt32(&signed_index)) {
   1162       *index = bit_cast<uint32_t>(signed_index);
   1163       return true;
   1164     }
   1165   }
   1166   return false;
   1167 }
   1168 
   1169 bool IsOutOfBoundsAccess(Handle<Object> receiver, uint32_t index) {
   1170   uint32_t length = 0;
   1171   if (receiver->IsJSArray()) {
   1172     JSArray::cast(*receiver)->length()->ToArrayLength(&length);
   1173   } else if (receiver->IsString()) {
   1174     length = String::cast(*receiver)->length();
   1175   } else if (receiver->IsJSObject()) {
   1176     length = JSObject::cast(*receiver)->elements()->length();
   1177   } else {
   1178     return false;
   1179   }
   1180   return index >= length;
   1181 }
   1182 
   1183 KeyedAccessLoadMode GetLoadMode(Isolate* isolate, Handle<Object> receiver,
   1184                                 uint32_t index) {
   1185   if (IsOutOfBoundsAccess(receiver, index)) {
   1186     if (receiver->IsJSTypedArray()) {
   1187       // For JSTypedArray we never lookup elements in the prototype chain.
   1188       return LOAD_IGNORE_OUT_OF_BOUNDS;
   1189     }
   1190 
   1191     // For other {receiver}s we need to check the "no elements" protector.
   1192     if (isolate->IsNoElementsProtectorIntact()) {
   1193       if (receiver->IsString()) {
   1194         // ToObject(receiver) will have the initial String.prototype.
   1195         return LOAD_IGNORE_OUT_OF_BOUNDS;
   1196       }
   1197       if (receiver->IsJSObject()) {
   1198         // For other JSObjects (including JSArrays) we can only continue if
   1199         // the {receiver}s prototype is either the initial Object.prototype
   1200         // or the initial Array.prototype, which are both guarded by the
   1201         // "no elements" protector checked above.
   1202         Handle<Object> receiver_prototype(
   1203             JSObject::cast(*receiver)->map()->prototype(), isolate);
   1204         if (isolate->IsInAnyContext(*receiver_prototype,
   1205                                     Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
   1206             isolate->IsInAnyContext(*receiver_prototype,
   1207                                     Context::INITIAL_OBJECT_PROTOTYPE_INDEX)) {
   1208           return LOAD_IGNORE_OUT_OF_BOUNDS;
   1209         }
   1210       }
   1211     }
   1212   }
   1213   return STANDARD_LOAD;
   1214 }
   1215 
   1216 }  // namespace
   1217 
   1218 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
   1219                                       Handle<Object> key) {
   1220   if (MigrateDeprecated(object)) {
   1221     Handle<Object> result;
   1222     ASSIGN_RETURN_ON_EXCEPTION(
   1223         isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
   1224         Object);
   1225     return result;
   1226   }
   1227 
   1228   Handle<Object> load_handle;
   1229 
   1230   // Check for non-string values that can be converted into an
   1231   // internalized string directly or is representable as a smi.
   1232   key = TryConvertKey(key, isolate());
   1233 
   1234   uint32_t index;
   1235   if ((key->IsInternalizedString() &&
   1236        !String::cast(*key)->AsArrayIndex(&index)) ||
   1237       key->IsSymbol()) {
   1238     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
   1239                                LoadIC::Load(object, Handle<Name>::cast(key)),
   1240                                Object);
   1241   } else if (ConvertKeyToIndex(object, key, &index)) {
   1242     KeyedAccessLoadMode load_mode = GetLoadMode(isolate(), object, index);
   1243     UpdateLoadElement(Handle<HeapObject>::cast(object), load_mode);
   1244     if (is_vector_set()) {
   1245       TraceIC("LoadIC", key);
   1246     }
   1247   }
   1248 
   1249   if (vector_needs_update()) {
   1250     ConfigureVectorState(MEGAMORPHIC, key);
   1251     TraceIC("LoadIC", key);
   1252   }
   1253 
   1254   if (!load_handle.is_null()) return load_handle;
   1255 
   1256   Handle<Object> result;
   1257   ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
   1258                              Runtime::GetObjectProperty(isolate(), object, key),
   1259                              Object);
   1260   return result;
   1261 }
   1262 
   1263 
   1264 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
   1265                              JSReceiver::StoreFromKeyed store_mode) {
   1266   // Disable ICs for non-JSObjects for now.
   1267   Handle<Object> object = it->GetReceiver();
   1268   if (object->IsJSProxy()) return true;
   1269   if (!object->IsJSObject()) return false;
   1270   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
   1271   DCHECK(!receiver->map()->is_deprecated());
   1272 
   1273   if (it->state() != LookupIterator::TRANSITION) {
   1274     for (; it->IsFound(); it->Next()) {
   1275       switch (it->state()) {
   1276         case LookupIterator::NOT_FOUND:
   1277         case LookupIterator::TRANSITION:
   1278           UNREACHABLE();
   1279         case LookupIterator::JSPROXY:
   1280           return true;
   1281         case LookupIterator::INTERCEPTOR: {
   1282           Handle<JSObject> holder = it->GetHolder<JSObject>();
   1283           InterceptorInfo* info = holder->GetNamedInterceptor();
   1284           if (it->HolderIsReceiverOrHiddenPrototype()) {
   1285             return !info->non_masking() && receiver.is_identical_to(holder) &&
   1286                    !info->setter()->IsUndefined(isolate());
   1287           } else if (!info->getter()->IsUndefined(isolate()) ||
   1288                      !info->query()->IsUndefined(isolate())) {
   1289             return false;
   1290           }
   1291           break;
   1292         }
   1293         case LookupIterator::ACCESS_CHECK:
   1294           if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
   1295           break;
   1296         case LookupIterator::ACCESSOR:
   1297           return !it->IsReadOnly();
   1298         case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1299           return false;
   1300         case LookupIterator::DATA: {
   1301           if (it->IsReadOnly()) return false;
   1302           Handle<JSObject> holder = it->GetHolder<JSObject>();
   1303           if (receiver.is_identical_to(holder)) {
   1304             it->PrepareForDataProperty(value);
   1305             // The previous receiver map might just have been deprecated,
   1306             // so reload it.
   1307             update_receiver_map(receiver);
   1308             return true;
   1309           }
   1310 
   1311           // Receiver != holder.
   1312           if (receiver->IsJSGlobalProxy()) {
   1313             PrototypeIterator iter(isolate(), receiver);
   1314             return it->GetHolder<Object>().is_identical_to(
   1315                 PrototypeIterator::GetCurrent(iter));
   1316           }
   1317 
   1318           if (it->HolderIsReceiverOrHiddenPrototype()) return false;
   1319 
   1320           if (it->ExtendingNonExtensible(receiver)) return false;
   1321           it->PrepareTransitionToDataProperty(receiver, value, NONE,
   1322                                               store_mode);
   1323           return it->IsCacheableTransition();
   1324         }
   1325       }
   1326     }
   1327   }
   1328 
   1329   receiver = it->GetStoreTarget<JSObject>();
   1330   if (it->ExtendingNonExtensible(receiver)) return false;
   1331   it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
   1332   return it->IsCacheableTransition();
   1333 }
   1334 
   1335 MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
   1336                                          Handle<Object> value) {
   1337   DCHECK(name->IsString());
   1338 
   1339   // Look up in script context table.
   1340   Handle<String> str_name = Handle<String>::cast(name);
   1341   Handle<JSGlobalObject> global = isolate()->global_object();
   1342   Handle<ScriptContextTable> script_contexts(
   1343       global->native_context()->script_context_table(), isolate());
   1344 
   1345   ScriptContextTable::LookupResult lookup_result;
   1346   if (ScriptContextTable::Lookup(isolate(), script_contexts, str_name,
   1347                                  &lookup_result)) {
   1348     Handle<Context> script_context = ScriptContextTable::GetContext(
   1349         isolate(), script_contexts, lookup_result.context_index);
   1350     if (lookup_result.mode == VariableMode::kConst) {
   1351       return TypeError(MessageTemplate::kConstAssign, global, name);
   1352     }
   1353 
   1354     Handle<Object> previous_value =
   1355         FixedArray::get(*script_context, lookup_result.slot_index, isolate());
   1356 
   1357     if (previous_value->IsTheHole(isolate())) {
   1358       // Do not install stubs and stay pre-monomorphic for
   1359       // uninitialized accesses.
   1360       return ReferenceError(name);
   1361     }
   1362 
   1363     if (FLAG_use_ic) {
   1364       if (nexus()->ConfigureLexicalVarMode(lookup_result.context_index,
   1365                                            lookup_result.slot_index)) {
   1366         TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_StoreScriptContextField);
   1367       } else {
   1368         // Given combination of indices can't be encoded, so use slow stub.
   1369         TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_SlowStub);
   1370         PatchCache(name, slow_stub());
   1371       }
   1372       TraceIC("StoreGlobalIC", name);
   1373     }
   1374 
   1375     script_context->set(lookup_result.slot_index, *value);
   1376     return value;
   1377   }
   1378 
   1379   return StoreIC::Store(global, name, value);
   1380 }
   1381 
   1382 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
   1383                                    Handle<Object> value,
   1384                                    JSReceiver::StoreFromKeyed store_mode) {
   1385   // TODO(verwaest): Let SetProperty do the migration, since storing a property
   1386   // might deprecate the current map again, if value does not fit.
   1387   if (MigrateDeprecated(object)) {
   1388     Handle<Object> result;
   1389     ASSIGN_RETURN_ON_EXCEPTION(
   1390         isolate(), result,
   1391         Object::SetProperty(isolate(), object, name, value, language_mode()),
   1392         Object);
   1393     return result;
   1394   }
   1395 
   1396   // If the object is undefined or null it's illegal to try to set any
   1397   // properties on it; throw a TypeError in that case.
   1398   if (object->IsNullOrUndefined(isolate())) {
   1399     if (FLAG_use_ic && state() != PREMONOMORPHIC) {
   1400       // Ensure the IC state progresses.
   1401       TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
   1402       update_receiver_map(object);
   1403       PatchCache(name, slow_stub());
   1404       TraceIC("StoreIC", name);
   1405     }
   1406     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
   1407   }
   1408 
   1409   if (state() != UNINITIALIZED) {
   1410     JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
   1411   }
   1412   LookupIterator it(isolate(), object, name);
   1413   bool use_ic = FLAG_use_ic;
   1414 
   1415   if (name->IsPrivate()) {
   1416     if (name->IsPrivateField() && !it.IsFound()) {
   1417       return TypeError(MessageTemplate::kInvalidPrivateFieldAccess, object,
   1418                        name);
   1419     }
   1420 
   1421     // IC handling of private fields/symbols stores on JSProxy is not
   1422     // supported.
   1423     if (object->IsJSProxy()) {
   1424       use_ic = false;
   1425     }
   1426   }
   1427   if (use_ic) UpdateCaches(&it, value, store_mode);
   1428 
   1429   MAYBE_RETURN_NULL(
   1430       Object::SetProperty(&it, value, language_mode(), store_mode));
   1431   return value;
   1432 }
   1433 
   1434 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
   1435                            JSReceiver::StoreFromKeyed store_mode) {
   1436   if (state() == UNINITIALIZED && !IsStoreGlobalIC()) {
   1437     // This is the first time we execute this inline cache. Transition
   1438     // to premonomorphic state to delay setting the monomorphic state.
   1439     TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic);
   1440     ConfigureVectorState(receiver_map());
   1441     TraceIC("StoreIC", lookup->name());
   1442     return;
   1443   }
   1444 
   1445   MaybeObjectHandle handler;
   1446   if (LookupForWrite(lookup, value, store_mode)) {
   1447     if (IsStoreGlobalIC()) {
   1448       if (lookup->state() == LookupIterator::DATA &&
   1449           lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
   1450         DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
   1451         // Now update the cell in the feedback vector.
   1452         nexus()->ConfigurePropertyCellMode(lookup->GetPropertyCell());
   1453         TraceIC("StoreGlobalIC", lookup->name());
   1454         return;
   1455       }
   1456     }
   1457     handler = ComputeHandler(lookup);
   1458   } else {
   1459     set_slow_stub_reason("LookupForWrite said 'false'");
   1460     // TODO(marja): change slow_stub to return MaybeObjectHandle.
   1461     handler = MaybeObjectHandle(slow_stub());
   1462   }
   1463 
   1464   PatchCache(lookup->name(), handler);
   1465   TraceIC("StoreIC", lookup->name());
   1466 }
   1467 
   1468 MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
   1469   switch (lookup->state()) {
   1470     case LookupIterator::TRANSITION: {
   1471       Handle<JSObject> store_target = lookup->GetStoreTarget<JSObject>();
   1472       if (store_target->IsJSGlobalObject()) {
   1473         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);
   1474 
   1475         if (receiver_map()->IsJSGlobalObject()) {
   1476           DCHECK(IsStoreGlobalIC());
   1477 #ifdef DEBUG
   1478           Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1479           DCHECK_EQ(*lookup->GetReceiver(), *holder);
   1480           DCHECK_EQ(*store_target, *holder);
   1481 #endif
   1482           return StoreHandler::StoreGlobal(lookup->transition_cell());
   1483         }
   1484 
   1485         Handle<Smi> smi_handler = StoreHandler::StoreGlobalProxy(isolate());
   1486         Handle<Object> handler = StoreHandler::StoreThroughPrototype(
   1487             isolate(), receiver_map(), store_target, smi_handler,
   1488             MaybeObjectHandle::Weak(lookup->transition_cell()));
   1489         return MaybeObjectHandle(handler);
   1490       }
   1491       // Dictionary-to-fast transitions are not expected and not supported.
   1492       DCHECK_IMPLIES(!lookup->transition_map()->is_dictionary_map(),
   1493                      !receiver_map()->is_dictionary_map());
   1494 
   1495       DCHECK(lookup->IsCacheableTransition());
   1496 
   1497       return StoreHandler::StoreTransition(isolate(), lookup->transition_map());
   1498     }
   1499 
   1500     case LookupIterator::INTERCEPTOR: {
   1501       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1502       USE(holder);
   1503 
   1504       DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
   1505       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
   1506       StoreInterceptorStub stub(isolate());
   1507       return MaybeObjectHandle(stub.GetCode());
   1508     }
   1509 
   1510     case LookupIterator::ACCESSOR: {
   1511       // This is currently guaranteed by checks in StoreIC::Store.
   1512       Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
   1513       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1514       DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
   1515 
   1516       if (!holder->HasFastProperties()) {
   1517         set_slow_stub_reason("accessor on slow map");
   1518         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1519         return MaybeObjectHandle(slow_stub());
   1520       }
   1521       Handle<Object> accessors = lookup->GetAccessors();
   1522       if (accessors->IsAccessorInfo()) {
   1523         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
   1524         if (v8::ToCData<Address>(info->setter()) == kNullAddress) {
   1525           set_slow_stub_reason("setter == kNullAddress");
   1526           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1527           return MaybeObjectHandle(slow_stub());
   1528         }
   1529         if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
   1530             !lookup->HolderIsReceiverOrHiddenPrototype()) {
   1531           set_slow_stub_reason("special data property in prototype chain");
   1532           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1533           return MaybeObjectHandle(slow_stub());
   1534         }
   1535         if (!AccessorInfo::IsCompatibleReceiverMap(info, receiver_map())) {
   1536           set_slow_stub_reason("incompatible receiver type");
   1537           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1538           return MaybeObjectHandle(slow_stub());
   1539         }
   1540 
   1541         Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty(
   1542             isolate(), lookup->GetAccessorIndex());
   1543         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyDH);
   1544         if (receiver.is_identical_to(holder)) {
   1545           return MaybeObjectHandle(smi_handler);
   1546         }
   1547         TRACE_HANDLER_STATS(isolate(),
   1548                             StoreIC_StoreNativeDataPropertyOnPrototypeDH);
   1549         return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
   1550             isolate(), receiver_map(), holder, smi_handler));
   1551 
   1552       } else if (accessors->IsAccessorPair()) {
   1553         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
   1554                               isolate());
   1555         if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
   1556           set_slow_stub_reason("setter not a function");
   1557           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1558           return MaybeObjectHandle(slow_stub());
   1559         }
   1560 
   1561         if (setter->IsFunctionTemplateInfo() &&
   1562             FunctionTemplateInfo::cast(*setter)->BreakAtEntry()) {
   1563           // Do not install an IC if the api function has a breakpoint.
   1564           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1565           return MaybeObjectHandle(slow_stub());
   1566         }
   1567 
   1568         CallOptimization call_optimization(isolate(), setter);
   1569         if (call_optimization.is_simple_api_call()) {
   1570           if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
   1571             CallOptimization::HolderLookup holder_lookup;
   1572             call_optimization.LookupHolderOfExpectedType(receiver_map(),
   1573                                                          &holder_lookup);
   1574 
   1575             Handle<Smi> smi_handler = StoreHandler::StoreApiSetter(
   1576                 isolate(),
   1577                 holder_lookup == CallOptimization::kHolderIsReceiver);
   1578 
   1579             Handle<Context> context(
   1580                 call_optimization.GetAccessorContext(holder->map()), isolate());
   1581             TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH);
   1582             return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
   1583                 isolate(), receiver_map(), holder, smi_handler,
   1584                 MaybeObjectHandle::Weak(call_optimization.api_call_info()),
   1585                 MaybeObjectHandle::Weak(context)));
   1586           }
   1587           set_slow_stub_reason("incompatible receiver");
   1588           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1589           return MaybeObjectHandle(slow_stub());
   1590         } else if (setter->IsFunctionTemplateInfo()) {
   1591           set_slow_stub_reason("setter non-simple template");
   1592           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1593           return MaybeObjectHandle(slow_stub());
   1594         }
   1595 
   1596         Handle<Smi> smi_handler =
   1597             StoreHandler::StoreAccessor(isolate(), lookup->GetAccessorIndex());
   1598 
   1599         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorDH);
   1600         if (receiver.is_identical_to(holder)) {
   1601           return MaybeObjectHandle(smi_handler);
   1602         }
   1603         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH);
   1604 
   1605         return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
   1606             isolate(), receiver_map(), holder, smi_handler));
   1607       }
   1608       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1609       return MaybeObjectHandle(slow_stub());
   1610     }
   1611 
   1612     case LookupIterator::DATA: {
   1613       // This is currently guaranteed by checks in StoreIC::Store.
   1614       Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
   1615       USE(receiver);
   1616       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
   1617       DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
   1618 
   1619       DCHECK_EQ(kData, lookup->property_details().kind());
   1620       if (lookup->is_dictionary_holder()) {
   1621         if (holder->IsJSGlobalObject()) {
   1622           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
   1623           return MaybeObjectHandle(
   1624               StoreHandler::StoreGlobal(lookup->GetPropertyCell()));
   1625         }
   1626         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
   1627         DCHECK(holder.is_identical_to(receiver));
   1628         return MaybeObjectHandle(StoreHandler::StoreNormal(isolate()));
   1629       }
   1630 
   1631       // -------------- Fields --------------
   1632       if (lookup->property_details().location() == kField) {
   1633         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
   1634         int descriptor = lookup->GetFieldDescriptorIndex();
   1635         FieldIndex index = lookup->GetFieldIndex();
   1636         PropertyConstness constness = lookup->constness();
   1637         if (constness == PropertyConstness::kConst &&
   1638             IsStoreOwnICKind(nexus()->kind())) {
   1639           // StoreOwnICs are used for initializing object literals therefore
   1640           // we must store the value unconditionally even to
   1641           // VariableMode::kConst fields.
   1642           constness = PropertyConstness::kMutable;
   1643         }
   1644         return MaybeObjectHandle(StoreHandler::StoreField(
   1645             isolate(), descriptor, index, constness, lookup->representation()));
   1646       }
   1647 
   1648       // -------------- Constant properties --------------
   1649       DCHECK_EQ(kDescriptor, lookup->property_details().location());
   1650       set_slow_stub_reason("constant property");
   1651       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
   1652       return MaybeObjectHandle(slow_stub());
   1653     }
   1654     case LookupIterator::JSPROXY: {
   1655       Handle<JSReceiver> receiver =
   1656           Handle<JSReceiver>::cast(lookup->GetReceiver());
   1657       Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
   1658       return MaybeObjectHandle(StoreHandler::StoreProxy(
   1659           isolate(), receiver_map(), holder, receiver));
   1660     }
   1661 
   1662     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1663     case LookupIterator::ACCESS_CHECK:
   1664     case LookupIterator::NOT_FOUND:
   1665       UNREACHABLE();
   1666   }
   1667   return MaybeObjectHandle();
   1668 }
   1669 
   1670 void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
   1671                                       KeyedAccessStoreMode store_mode,
   1672                                       bool receiver_was_cow) {
   1673   MapHandles target_receiver_maps;
   1674   TargetMaps(&target_receiver_maps);
   1675   if (target_receiver_maps.empty()) {
   1676     Handle<Map> monomorphic_map =
   1677         ComputeTransitionedMap(receiver_map, store_mode);
   1678     store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
   1679     Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
   1680     return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
   1681   }
   1682 
   1683   for (Handle<Map> map : target_receiver_maps) {
   1684     if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) {
   1685       DCHECK(!IsStoreInArrayLiteralICKind(kind()));
   1686       set_slow_stub_reason("JSValue");
   1687       return;
   1688     }
   1689   }
   1690 
   1691   // There are several special cases where an IC that is MONOMORPHIC can still
   1692   // transition to a different GetNonTransitioningStoreMode IC that handles a
   1693   // superset of the original IC. Handle those here if the receiver map hasn't
   1694   // changed or it has transitioned to a more general kind.
   1695   KeyedAccessStoreMode old_store_mode;
   1696   old_store_mode = GetKeyedAccessStoreMode();
   1697   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
   1698   if (state() == MONOMORPHIC) {
   1699     Handle<Map> transitioned_receiver_map = receiver_map;
   1700     if (IsTransitionStoreMode(store_mode)) {
   1701       transitioned_receiver_map =
   1702           ComputeTransitionedMap(receiver_map, store_mode);
   1703     }
   1704     if ((receiver_map.is_identical_to(previous_receiver_map) &&
   1705          IsTransitionStoreMode(store_mode)) ||
   1706         IsTransitionOfMonomorphicTarget(*previous_receiver_map,
   1707                                         *transitioned_receiver_map)) {
   1708       // If the "old" and "new" maps are in the same elements map family, or
   1709       // if they at least come from the same origin for a transitioning store,
   1710       // stay MONOMORPHIC and use the map for the most generic ElementsKind.
   1711       store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
   1712       Handle<Object> handler =
   1713           StoreElementHandler(transitioned_receiver_map, store_mode);
   1714       ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
   1715       return;
   1716     }
   1717     if (receiver_map.is_identical_to(previous_receiver_map) &&
   1718         old_store_mode == STANDARD_STORE &&
   1719         (store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
   1720          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1721          store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
   1722       // A "normal" IC that handles stores can switch to a version that can
   1723       // grow at the end of the array, handle OOB accesses or copy COW arrays
   1724       // and still stay MONOMORPHIC.
   1725       Handle<Object> handler = StoreElementHandler(receiver_map, store_mode);
   1726       return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
   1727     }
   1728   }
   1729 
   1730   DCHECK(state() != GENERIC);
   1731 
   1732   bool map_added =
   1733       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
   1734 
   1735   if (IsTransitionStoreMode(store_mode)) {
   1736     Handle<Map> transitioned_receiver_map =
   1737         ComputeTransitionedMap(receiver_map, store_mode);
   1738     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
   1739                                             transitioned_receiver_map);
   1740   }
   1741 
   1742   if (!map_added) {
   1743     // If the miss wasn't due to an unseen map, a polymorphic stub
   1744     // won't help, use the megamorphic stub which can handle everything.
   1745     set_slow_stub_reason("same map added twice");
   1746     return;
   1747   }
   1748 
   1749   // If the maximum number of receiver maps has been exceeded, use the
   1750   // megamorphic version of the IC.
   1751   if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return;
   1752 
   1753   // Make sure all polymorphic handlers have the same store mode, otherwise the
   1754   // megamorphic stub must be used.
   1755   store_mode = GetNonTransitioningStoreMode(store_mode, receiver_was_cow);
   1756   if (old_store_mode != STANDARD_STORE) {
   1757     if (store_mode == STANDARD_STORE) {
   1758       store_mode = old_store_mode;
   1759     } else if (store_mode != old_store_mode) {
   1760       set_slow_stub_reason("store mode mismatch");
   1761       return;
   1762     }
   1763   }
   1764 
   1765   // If the store mode isn't the standard mode, make sure that all polymorphic
   1766   // receivers are either external arrays, or all "normal" arrays. Otherwise,
   1767   // use the megamorphic stub.
   1768   if (store_mode != STANDARD_STORE) {
   1769     size_t external_arrays = 0;
   1770     for (Handle<Map> map : target_receiver_maps) {
   1771       if (map->has_fixed_typed_array_elements()) {
   1772         DCHECK(!IsStoreInArrayLiteralICKind(kind()));
   1773         external_arrays++;
   1774       }
   1775     }
   1776     if (external_arrays != 0 &&
   1777         external_arrays != target_receiver_maps.size()) {
   1778       DCHECK(!IsStoreInArrayLiteralICKind(kind()));
   1779       set_slow_stub_reason(
   1780           "unsupported combination of external and normal arrays");
   1781       return;
   1782     }
   1783   }
   1784 
   1785   MaybeObjectHandles handlers;
   1786   handlers.reserve(target_receiver_maps.size());
   1787   StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
   1788   if (target_receiver_maps.size() == 0) {
   1789     // Transition to PREMONOMORPHIC state here and remember a weak-reference
   1790     // to the {receiver_map} in case TurboFan sees this function before the
   1791     // IC can transition further.
   1792     ConfigureVectorState(receiver_map);
   1793   } else if (target_receiver_maps.size() == 1) {
   1794     ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
   1795   } else {
   1796     ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
   1797   }
   1798 }
   1799 
   1800 
   1801 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
   1802     Handle<Map> map, KeyedAccessStoreMode store_mode) {
   1803   switch (store_mode) {
   1804     case STORE_TRANSITION_TO_OBJECT:
   1805     case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
   1806       ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
   1807                               ? HOLEY_ELEMENTS
   1808                               : PACKED_ELEMENTS;
   1809       return Map::TransitionElementsTo(isolate(), map, kind);
   1810     }
   1811     case STORE_TRANSITION_TO_DOUBLE:
   1812     case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
   1813       ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
   1814                               ? HOLEY_DOUBLE_ELEMENTS
   1815                               : PACKED_DOUBLE_ELEMENTS;
   1816       return Map::TransitionElementsTo(isolate(), map, kind);
   1817     }
   1818     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
   1819       DCHECK(map->has_fixed_typed_array_elements());
   1820       V8_FALLTHROUGH;
   1821     case STORE_NO_TRANSITION_HANDLE_COW:
   1822     case STANDARD_STORE:
   1823     case STORE_AND_GROW_NO_TRANSITION_HANDLE_COW:
   1824       return map;
   1825   }
   1826   UNREACHABLE();
   1827 }
   1828 
   1829 Handle<Object> KeyedStoreIC::StoreElementHandler(
   1830     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
   1831   DCHECK(store_mode == STANDARD_STORE ||
   1832          store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
   1833          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1834          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
   1835   DCHECK_IMPLIES(
   1836       receiver_map->DictionaryElementsInPrototypeChainOnly(isolate()),
   1837       IsStoreInArrayLiteralICKind(kind()));
   1838 
   1839   if (receiver_map->IsJSProxyMap()) {
   1840     return StoreHandler::StoreProxy(isolate());
   1841   }
   1842 
   1843   // TODO(ishell): move to StoreHandler::StoreElement().
   1844   ElementsKind elements_kind = receiver_map->elements_kind();
   1845   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
   1846   Handle<Code> stub;
   1847   if (receiver_map->has_sloppy_arguments_elements()) {
   1848     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
   1849     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
   1850   } else if (receiver_map->has_fast_elements() ||
   1851              receiver_map->has_fixed_typed_array_elements()) {
   1852     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
   1853     stub =
   1854         StoreFastElementStub(isolate(), is_jsarray, elements_kind, store_mode)
   1855             .GetCode();
   1856     if (receiver_map->has_fixed_typed_array_elements()) return stub;
   1857   } else if (IsStoreInArrayLiteralICKind(kind())) {
   1858     TRACE_HANDLER_STATS(isolate(), StoreInArrayLiteralIC_SlowStub);
   1859     stub = StoreInArrayLiteralSlowStub(isolate(), store_mode).GetCode();
   1860   } else {
   1861     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
   1862     DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
   1863     stub = StoreSlowElementStub(isolate(), store_mode).GetCode();
   1864   }
   1865 
   1866   if (IsStoreInArrayLiteralICKind(kind())) return stub;
   1867 
   1868   Handle<Object> validity_cell =
   1869       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
   1870   if (validity_cell->IsSmi()) {
   1871     // There's no prototype validity cell to check, so we can just use the stub.
   1872     return stub;
   1873   }
   1874   Handle<StoreHandler> handler = isolate()->factory()->NewStoreHandler(0);
   1875   handler->set_validity_cell(*validity_cell);
   1876   handler->set_smi_handler(*stub);
   1877   return handler;
   1878 }
   1879 
   1880 void KeyedStoreIC::StoreElementPolymorphicHandlers(
   1881     MapHandles* receiver_maps, MaybeObjectHandles* handlers,
   1882     KeyedAccessStoreMode store_mode) {
   1883   DCHECK(store_mode == STANDARD_STORE ||
   1884          store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
   1885          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
   1886          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
   1887 
   1888   // Filter out deprecated maps to ensure their instances get migrated.
   1889   receiver_maps->erase(
   1890       std::remove_if(
   1891           receiver_maps->begin(), receiver_maps->end(),
   1892           [](const Handle<Map>& map) { return map->is_deprecated(); }),
   1893       receiver_maps->end());
   1894 
   1895   for (Handle<Map> receiver_map : *receiver_maps) {
   1896     Handle<Object> handler;
   1897     Handle<Map> transition;
   1898 
   1899     if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
   1900         receiver_map->DictionaryElementsInPrototypeChainOnly(isolate())) {
   1901       // TODO(mvstanton): Consider embedding store_mode in the state of the slow
   1902       // keyed store ic for uniformity.
   1903       TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
   1904       handler = slow_stub();
   1905 
   1906     } else {
   1907       {
   1908         Map* tmap = receiver_map->FindElementsKindTransitionedMap(
   1909             isolate(), *receiver_maps);
   1910         if (tmap != nullptr) {
   1911           if (receiver_map->is_stable()) {
   1912             receiver_map->NotifyLeafMapLayoutChange(isolate());
   1913           }
   1914           transition = handle(tmap, isolate());
   1915         }
   1916       }
   1917 
   1918       // TODO(mvstanton): The code below is doing pessimistic elements
   1919       // transitions. I would like to stop doing that and rely on Allocation
   1920       // Site Tracking to do a better job of ensuring the data types are what
   1921       // they need to be. Not all the elements are in place yet, pessimistic
   1922       // elements transitions are still important for performance.
   1923       if (!transition.is_null()) {
   1924         TRACE_HANDLER_STATS(isolate(),
   1925                             KeyedStoreIC_ElementsTransitionAndStoreStub);
   1926         handler = StoreHandler::StoreElementTransition(isolate(), receiver_map,
   1927                                                        transition, store_mode);
   1928       } else {
   1929         handler = StoreElementHandler(receiver_map, store_mode);
   1930       }
   1931     }
   1932     DCHECK(!handler.is_null());
   1933     handlers->push_back(MaybeObjectHandle(handler));
   1934   }
   1935 }
   1936 
   1937 
   1938 static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
   1939                                          uint32_t index, Handle<Object> value) {
   1940   bool oob_access = IsOutOfBoundsAccess(receiver, index);
   1941   // Don't consider this a growing store if the store would send the receiver to
   1942   // dictionary mode.
   1943   bool allow_growth = receiver->IsJSArray() && oob_access &&
   1944                       !receiver->WouldConvertToSlowElements(index);
   1945   if (allow_growth) {
   1946     // Handle growing array in stub if necessary.
   1947     if (receiver->HasSmiElements()) {
   1948       if (value->IsHeapNumber()) {
   1949         return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
   1950       }
   1951       if (value->IsHeapObject()) {
   1952         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
   1953       }
   1954     } else if (receiver->HasDoubleElements()) {
   1955       if (!value->IsSmi() && !value->IsHeapNumber()) {
   1956         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
   1957       }
   1958     }
   1959     return STORE_AND_GROW_NO_TRANSITION_HANDLE_COW;
   1960   } else {
   1961     // Handle only in-bounds elements accesses.
   1962     if (receiver->HasSmiElements()) {
   1963       if (value->IsHeapNumber()) {
   1964         return STORE_TRANSITION_TO_DOUBLE;
   1965       } else if (value->IsHeapObject()) {
   1966         return STORE_TRANSITION_TO_OBJECT;
   1967       }
   1968     } else if (receiver->HasDoubleElements()) {
   1969       if (!value->IsSmi() && !value->IsHeapNumber()) {
   1970         return STORE_TRANSITION_TO_OBJECT;
   1971       }
   1972     }
   1973     if (!FLAG_trace_external_array_abuse &&
   1974         receiver->map()->has_fixed_typed_array_elements() && oob_access) {
   1975       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
   1976     }
   1977     return receiver->elements()->IsCowArray() ? STORE_NO_TRANSITION_HANDLE_COW
   1978                                               : STANDARD_STORE;
   1979   }
   1980 }
   1981 
   1982 
   1983 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
   1984                                         Handle<Object> key,
   1985                                         Handle<Object> value) {
   1986   // TODO(verwaest): Let SetProperty do the migration, since storing a property
   1987   // might deprecate the current map again, if value does not fit.
   1988   if (MigrateDeprecated(object)) {
   1989     Handle<Object> result;
   1990     ASSIGN_RETURN_ON_EXCEPTION(
   1991         isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
   1992                                                       value, language_mode()),
   1993         Object);
   1994     return result;
   1995   }
   1996 
   1997   // Check for non-string values that can be converted into an
   1998   // internalized string directly or is representable as a smi.
   1999   key = TryConvertKey(key, isolate());
   2000 
   2001   Handle<Object> store_handle;
   2002 
   2003   uint32_t index;
   2004   if ((key->IsInternalizedString() &&
   2005        !String::cast(*key)->AsArrayIndex(&index)) ||
   2006       key->IsSymbol()) {
   2007     ASSIGN_RETURN_ON_EXCEPTION(
   2008         isolate(), store_handle,
   2009         StoreIC::Store(object, Handle<Name>::cast(key), value,
   2010                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
   2011         Object);
   2012     if (vector_needs_update()) {
   2013       if (ConfigureVectorState(MEGAMORPHIC, key)) {
   2014         set_slow_stub_reason("unhandled internalized string key");
   2015         TraceIC("StoreIC", key);
   2016       }
   2017     }
   2018     return store_handle;
   2019   }
   2020 
   2021   JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
   2022 
   2023   bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
   2024                 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
   2025   if (use_ic && !object->IsSmi()) {
   2026     // Don't use ICs for maps of the objects in Array's prototype chain. We
   2027     // expect to be able to trap element sets to objects with those maps in
   2028     // the runtime to enable optimization of element hole access.
   2029     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
   2030     if (heap_object->map()->IsMapInArrayPrototypeChain(isolate())) {
   2031       set_slow_stub_reason("map in array prototype");
   2032       use_ic = false;
   2033     }
   2034   }
   2035 
   2036   Handle<Map> old_receiver_map;
   2037   bool is_arguments = false;
   2038   bool key_is_valid_index = false;
   2039   KeyedAccessStoreMode store_mode = STANDARD_STORE;
   2040   if (use_ic && object->IsJSReceiver()) {
   2041     Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
   2042     old_receiver_map = handle(receiver->map(), isolate());
   2043     is_arguments = receiver->IsJSArgumentsObject();
   2044     bool is_proxy = receiver->IsJSProxy();
   2045     // For JSTypedArray {object}s we can handle negative indices as OOB
   2046     // accesses, since integer indexed properties are never looked up
   2047     // on the prototype chain. For this we simply map the negative {key}s
   2048     // to the [2**31,2**32-1] range, which is safe since JSTypedArray::length
   2049     // is always an unsigned Smi.
   2050     key_is_valid_index =
   2051         key->IsSmi() && (Smi::ToInt(*key) >= 0 || object->IsJSTypedArray());
   2052     if (!is_arguments && !is_proxy) {
   2053       if (key_is_valid_index) {
   2054         uint32_t index = static_cast<uint32_t>(Smi::ToInt(*key));
   2055         Handle<JSObject> receiver_object = Handle<JSObject>::cast(object);
   2056         store_mode = GetStoreMode(receiver_object, index, value);
   2057       }
   2058     }
   2059   }
   2060 
   2061   DCHECK(store_handle.is_null());
   2062   bool receiver_was_cow =
   2063       object->IsJSArray() &&
   2064       Handle<JSArray>::cast(object)->elements()->IsCowArray();
   2065   ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
   2066                              Runtime::SetObjectProperty(isolate(), object, key,
   2067                                                         value, language_mode()),
   2068                              Object);
   2069 
   2070   if (use_ic) {
   2071     if (!old_receiver_map.is_null()) {
   2072       if (is_arguments) {
   2073         set_slow_stub_reason("arguments receiver");
   2074       } else if (key_is_valid_index) {
   2075         if (old_receiver_map->is_abandoned_prototype_map()) {
   2076           set_slow_stub_reason("receiver with prototype map");
   2077         } else if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly(
   2078                        isolate())) {
   2079           // We should go generic if receiver isn't a dictionary, but our
   2080           // prototype chain does have dictionary elements. This ensures that
   2081           // other non-dictionary receivers in the polymorphic case benefit
   2082           // from fast path keyed stores.
   2083           UpdateStoreElement(old_receiver_map, store_mode, receiver_was_cow);
   2084         } else {
   2085           set_slow_stub_reason("dictionary or proxy prototype");
   2086         }
   2087       } else {
   2088         set_slow_stub_reason("non-smi-like key");
   2089       }
   2090     } else {
   2091       set_slow_stub_reason("non-JSObject receiver");
   2092     }
   2093   }
   2094 
   2095   if (vector_needs_update()) {
   2096     ConfigureVectorState(MEGAMORPHIC, key);
   2097   }
   2098   TraceIC("StoreIC", key);
   2099 
   2100   return store_handle;
   2101 }
   2102 
   2103 namespace {
   2104 void StoreOwnElement(Isolate* isolate, Handle<JSArray> array,
   2105                      Handle<Object> index, Handle<Object> value) {
   2106   DCHECK(index->IsNumber());
   2107   bool success = false;
   2108   LookupIterator it = LookupIterator::PropertyOrElement(
   2109       isolate, array, index, &success, LookupIterator::OWN);
   2110   DCHECK(success);
   2111 
   2112   CHECK(JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE,
   2113                                                     kThrowOnError)
   2114             .FromJust());
   2115 }
   2116 }  // namespace
   2117 
   2118 void StoreInArrayLiteralIC::Store(Handle<JSArray> array, Handle<Object> index,
   2119                                   Handle<Object> value) {
   2120   DCHECK(!array->map()->IsMapInArrayPrototypeChain(isolate()));
   2121   DCHECK(index->IsNumber());
   2122 
   2123   if (!FLAG_use_ic || MigrateDeprecated(array)) {
   2124     StoreOwnElement(isolate(), array, index, value);
   2125     TraceIC("StoreInArrayLiteralIC", index);
   2126     return;
   2127   }
   2128 
   2129   // TODO(neis): Convert HeapNumber to Smi if possible?
   2130 
   2131   KeyedAccessStoreMode store_mode = STANDARD_STORE;
   2132   if (index->IsSmi()) {
   2133     DCHECK_GE(Smi::ToInt(*index), 0);
   2134     uint32_t index32 = static_cast<uint32_t>(Smi::ToInt(*index));
   2135     store_mode = GetStoreMode(array, index32, value);
   2136   }
   2137 
   2138   Handle<Map> old_array_map(array->map(), isolate());
   2139   bool array_was_cow = array->elements()->IsCowArray();
   2140   StoreOwnElement(isolate(), array, index, value);
   2141 
   2142   if (index->IsSmi()) {
   2143     DCHECK(!old_array_map->is_abandoned_prototype_map());
   2144     UpdateStoreElement(old_array_map, store_mode, array_was_cow);
   2145   } else {
   2146     set_slow_stub_reason("index out of Smi range");
   2147   }
   2148 
   2149   if (vector_needs_update()) {
   2150     ConfigureVectorState(MEGAMORPHIC, index);
   2151   }
   2152   TraceIC("StoreInArrayLiteralIC", index);
   2153 }
   2154 
   2155 // ----------------------------------------------------------------------------
   2156 // Static IC stub generators.
   2157 //
   2158 
   2159 RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
   2160   HandleScope scope(isolate);
   2161   DCHECK_EQ(4, args.length());
   2162   // Runtime functions don't follow the IC's calling convention.
   2163   Handle<Object> receiver = args.at(0);
   2164   Handle<Name> key = args.at<Name>(1);
   2165   Handle<Smi> slot = args.at<Smi>(2);
   2166   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
   2167   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2168   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
   2169   // LoadIC miss handler if the handler misses. Since the vector Nexus is
   2170   // set up outside the IC, handle that here.
   2171   FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2172   if (IsLoadICKind(kind)) {
   2173     LoadIC ic(isolate, vector, vector_slot);
   2174     ic.UpdateState(receiver, key);
   2175     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   2176 
   2177   } else if (IsLoadGlobalICKind(kind)) {
   2178     DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
   2179     receiver = isolate->global_object();
   2180     LoadGlobalIC ic(isolate, vector, vector_slot);
   2181     ic.UpdateState(receiver, key);
   2182     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
   2183 
   2184   } else {
   2185     DCHECK(IsKeyedLoadICKind(kind));
   2186     KeyedLoadIC ic(isolate, vector, vector_slot);
   2187     ic.UpdateState(receiver, key);
   2188     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   2189   }
   2190 }
   2191 
   2192 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
   2193   HandleScope scope(isolate);
   2194   DCHECK_EQ(3, args.length());
   2195   // Runtime functions don't follow the IC's calling convention.
   2196   Handle<JSGlobalObject> global = isolate->global_object();
   2197   Handle<String> name = args.at<String>(0);
   2198   Handle<Smi> slot = args.at<Smi>(1);
   2199   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2200   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2201 
   2202   LoadGlobalIC ic(isolate, vector, vector_slot);
   2203   ic.UpdateState(global, name);
   2204 
   2205   Handle<Object> result;
   2206   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
   2207   return *result;
   2208 }
   2209 
   2210 RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
   2211   HandleScope scope(isolate);
   2212   DCHECK_EQ(3, args.length());
   2213   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
   2214 
   2215   Handle<Context> native_context = isolate->native_context();
   2216   Handle<ScriptContextTable> script_contexts(
   2217       native_context->script_context_table(), isolate);
   2218 
   2219   ScriptContextTable::LookupResult lookup_result;
   2220   if (ScriptContextTable::Lookup(isolate, script_contexts, name,
   2221                                  &lookup_result)) {
   2222     Handle<Context> script_context = ScriptContextTable::GetContext(
   2223         isolate, script_contexts, lookup_result.context_index);
   2224     Handle<Object> result =
   2225         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
   2226     if (*result == ReadOnlyRoots(isolate).the_hole_value()) {
   2227       THROW_NEW_ERROR_RETURN_FAILURE(
   2228           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
   2229     }
   2230     return *result;
   2231   }
   2232 
   2233   Handle<JSGlobalObject> global(native_context->global_object(), isolate);
   2234   Handle<Object> result;
   2235   bool is_found = false;
   2236   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2237       isolate, result,
   2238       Runtime::GetObjectProperty(isolate, global, name, &is_found));
   2239   if (!is_found) {
   2240     Handle<Smi> slot = args.at<Smi>(1);
   2241     Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2242     FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2243     FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2244     // It is actually a LoadGlobalICs here but the predicate handles this case
   2245     // properly.
   2246     if (LoadIC::ShouldThrowReferenceError(kind)) {
   2247       THROW_NEW_ERROR_RETURN_FAILURE(
   2248           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
   2249     }
   2250   }
   2251   return *result;
   2252 }
   2253 
   2254 RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
   2255   HandleScope scope(isolate);
   2256   DCHECK_EQ(4, args.length());
   2257   // Runtime functions don't follow the IC's calling convention.
   2258   Handle<Object> receiver = args.at(0);
   2259   Handle<Object> key = args.at(1);
   2260   Handle<Smi> slot = args.at<Smi>(2);
   2261   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
   2262   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2263   KeyedLoadIC ic(isolate, vector, vector_slot);
   2264   ic.UpdateState(receiver, key);
   2265   RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
   2266 }
   2267 
   2268 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
   2269   HandleScope scope(isolate);
   2270   DCHECK_EQ(5, args.length());
   2271   // Runtime functions don't follow the IC's calling convention.
   2272   Handle<Object> value = args.at(0);
   2273   Handle<Smi> slot = args.at<Smi>(1);
   2274   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2275   Handle<Object> receiver = args.at(3);
   2276   Handle<Name> key = args.at<Name>(4);
   2277   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2278   FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2279   if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) {
   2280     StoreIC ic(isolate, vector, vector_slot);
   2281     ic.UpdateState(receiver, key);
   2282     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   2283   } else if (IsStoreGlobalICKind(kind)) {
   2284     DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
   2285     receiver = isolate->global_object();
   2286     StoreGlobalIC ic(isolate, vector, vector_slot);
   2287     ic.UpdateState(receiver, key);
   2288     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(key, value));
   2289   } else {
   2290     DCHECK(IsKeyedStoreICKind(kind));
   2291     KeyedStoreIC ic(isolate, vector, vector_slot);
   2292     ic.UpdateState(receiver, key);
   2293     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   2294   }
   2295 }
   2296 
   2297 RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Miss) {
   2298   HandleScope scope(isolate);
   2299   DCHECK_EQ(4, args.length());
   2300   // Runtime functions don't follow the IC's calling convention.
   2301   Handle<Object> value = args.at(0);
   2302   Handle<Smi> slot = args.at<Smi>(1);
   2303   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2304   Handle<Name> key = args.at<Name>(3);
   2305   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2306   StoreGlobalIC ic(isolate, vector, vector_slot);
   2307   Handle<JSGlobalObject> global = isolate->global_object();
   2308   ic.UpdateState(global, key);
   2309   RETURN_RESULT_OR_FAILURE(isolate, ic.Store(key, value));
   2310 }
   2311 
   2312 RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
   2313   HandleScope scope(isolate);
   2314   DCHECK_EQ(5, args.length());
   2315   // Runtime functions don't follow the IC's calling convention.
   2316   Handle<Object> value = args.at(0);
   2317   Handle<Smi> slot = args.at<Smi>(1);
   2318   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2319   CONVERT_ARG_HANDLE_CHECKED(String, name, 4);
   2320 
   2321 #ifdef DEBUG
   2322   {
   2323     FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2324     FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
   2325     DCHECK(IsStoreGlobalICKind(slot_kind));
   2326     Handle<Object> receiver = args.at(3);
   2327     DCHECK(receiver->IsJSGlobalProxy());
   2328   }
   2329 #endif
   2330 
   2331   Handle<JSGlobalObject> global = isolate->global_object();
   2332   Handle<Context> native_context = isolate->native_context();
   2333   Handle<ScriptContextTable> script_contexts(
   2334       native_context->script_context_table(), isolate);
   2335 
   2336   ScriptContextTable::LookupResult lookup_result;
   2337   if (ScriptContextTable::Lookup(isolate, script_contexts, name,
   2338                                  &lookup_result)) {
   2339     Handle<Context> script_context = ScriptContextTable::GetContext(
   2340         isolate, script_contexts, lookup_result.context_index);
   2341     if (lookup_result.mode == VariableMode::kConst) {
   2342       THROW_NEW_ERROR_RETURN_FAILURE(
   2343           isolate, NewTypeError(MessageTemplate::kConstAssign, global, name));
   2344     }
   2345 
   2346     Handle<Object> previous_value =
   2347         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
   2348 
   2349     if (previous_value->IsTheHole(isolate)) {
   2350       THROW_NEW_ERROR_RETURN_FAILURE(
   2351           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
   2352     }
   2353 
   2354     script_context->set(lookup_result.slot_index, *value);
   2355     return *value;
   2356   }
   2357 
   2358   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2359   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
   2360   RETURN_RESULT_OR_FAILURE(
   2361       isolate,
   2362       Runtime::SetObjectProperty(isolate, global, name, value, language_mode));
   2363 }
   2364 
   2365 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
   2366   HandleScope scope(isolate);
   2367   DCHECK_EQ(5, args.length());
   2368   // Runtime functions don't follow the IC's calling convention.
   2369   Handle<Object> value = args.at(0);
   2370   Handle<Smi> slot = args.at<Smi>(1);
   2371   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2372   Handle<Object> receiver = args.at(3);
   2373   Handle<Object> key = args.at(4);
   2374   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2375   FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2376 
   2377   // The elements store stubs miss into this function, but they are shared by
   2378   // different ICs.
   2379   if (IsKeyedStoreICKind(kind)) {
   2380     KeyedStoreIC ic(isolate, vector, vector_slot);
   2381     ic.UpdateState(receiver, key);
   2382     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
   2383   } else {
   2384     DCHECK(IsStoreInArrayLiteralICKind(kind));
   2385     DCHECK(receiver->IsJSArray());
   2386     DCHECK(key->IsNumber());
   2387     StoreInArrayLiteralIC ic(isolate, vector, vector_slot);
   2388     ic.UpdateState(receiver, key);
   2389     ic.Store(Handle<JSArray>::cast(receiver), key, value);
   2390     return *value;
   2391   }
   2392 }
   2393 
   2394 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
   2395   HandleScope scope(isolate);
   2396   DCHECK_EQ(5, args.length());
   2397   // Runtime functions don't follow the IC's calling convention.
   2398   Handle<Object> value = args.at(0);
   2399   Handle<Smi> slot = args.at<Smi>(1);
   2400   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2401   Handle<Object> object = args.at(3);
   2402   Handle<Object> key = args.at(4);
   2403   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2404   FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2405   DCHECK(IsStoreICKind(kind) || IsKeyedStoreICKind(kind));
   2406   LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
   2407   RETURN_RESULT_OR_FAILURE(
   2408       isolate,
   2409       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
   2410 }
   2411 
   2412 RUNTIME_FUNCTION(Runtime_StoreInArrayLiteralIC_Slow) {
   2413   HandleScope scope(isolate);
   2414   DCHECK_EQ(3, args.length());
   2415   // Runtime functions don't follow the IC's calling convention.
   2416   Handle<Object> value = args.at(0);
   2417   Handle<Object> array = args.at(1);
   2418   Handle<Object> index = args.at(2);
   2419   StoreOwnElement(isolate, Handle<JSArray>::cast(array), index, value);
   2420   return *value;
   2421 }
   2422 
   2423 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
   2424   HandleScope scope(isolate);
   2425   DCHECK_EQ(6, args.length());
   2426   // Runtime functions don't follow the IC's calling convention.
   2427   Handle<Object> object = args.at(0);
   2428   Handle<Object> key = args.at(1);
   2429   Handle<Object> value = args.at(2);
   2430   Handle<Map> map = args.at<Map>(3);
   2431   Handle<Smi> slot = args.at<Smi>(4);
   2432   Handle<FeedbackVector> vector = args.at<FeedbackVector>(5);
   2433   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2434   FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2435 
   2436   if (object->IsJSObject()) {
   2437     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
   2438                                      map->elements_kind());
   2439   }
   2440 
   2441   if (IsStoreInArrayLiteralICKind(kind)) {
   2442     StoreOwnElement(isolate, Handle<JSArray>::cast(object), key, value);
   2443     return *value;
   2444   } else {
   2445     DCHECK(IsKeyedStoreICKind(kind) || IsStoreICKind(kind));
   2446     LanguageMode language_mode = GetLanguageModeFromSlotKind(kind);
   2447     RETURN_RESULT_OR_FAILURE(
   2448         isolate,
   2449         Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
   2450   }
   2451 }
   2452 
   2453 static bool CanFastCloneObject(Handle<Map> map) {
   2454   DisallowHeapAllocation no_gc;
   2455   if (map->IsNullOrUndefinedMap()) return true;
   2456   if (!map->IsJSObjectMap() ||
   2457       !IsSmiOrObjectElementsKind(map->elements_kind()) ||
   2458       !map->OnlyHasSimpleProperties()) {
   2459     return false;
   2460   }
   2461 
   2462   DescriptorArray* descriptors = map->instance_descriptors();
   2463   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
   2464     PropertyDetails details = descriptors->GetDetails(i);
   2465     Name* key = descriptors->GetKey(i);
   2466     if (details.kind() != kData || !details.IsEnumerable() ||
   2467         key->IsPrivateField()) {
   2468       return false;
   2469     }
   2470   }
   2471 
   2472   return true;
   2473 }
   2474 
   2475 static Handle<Map> FastCloneObjectMap(Isolate* isolate,
   2476                                       Handle<HeapObject> source, int flags) {
   2477   Handle<Map> source_map(source->map(), isolate);
   2478   SLOW_DCHECK(source->IsNullOrUndefined() || CanFastCloneObject(source_map));
   2479   Handle<JSFunction> constructor(isolate->native_context()->object_function(),
   2480                                  isolate);
   2481   DCHECK(constructor->has_initial_map());
   2482   Handle<Map> initial_map(constructor->initial_map(), isolate);
   2483   Handle<Map> map = initial_map;
   2484 
   2485   if (source_map->IsJSObjectMap() && source_map->GetInObjectProperties() !=
   2486                                          initial_map->GetInObjectProperties()) {
   2487     int inobject_properties = source_map->GetInObjectProperties();
   2488     int instance_size =
   2489         JSObject::kHeaderSize + kPointerSize * inobject_properties;
   2490     int unused = source_map->UnusedInObjectProperties();
   2491     DCHECK(instance_size <= JSObject::kMaxInstanceSize);
   2492     map = Map::CopyInitialMap(isolate, map, instance_size, inobject_properties,
   2493                               unused);
   2494   }
   2495 
   2496   if (flags & ObjectLiteral::kHasNullPrototype) {
   2497     if (map.is_identical_to(initial_map)) {
   2498       map = Map::Copy(isolate, map, "ObjectWithNullProto");
   2499     }
   2500     Map::SetPrototype(isolate, map, isolate->factory()->null_value());
   2501   }
   2502 
   2503   if (source->IsNullOrUndefined() || !source_map->NumberOfOwnDescriptors()) {
   2504     return map;
   2505   }
   2506 
   2507   if (map.is_identical_to(initial_map)) {
   2508     map = Map::Copy(isolate, map, "InitializeClonedDescriptors");
   2509   }
   2510 
   2511   Handle<DescriptorArray> source_descriptors(source_map->instance_descriptors(),
   2512                                              isolate);
   2513   int size = source_map->NumberOfOwnDescriptors();
   2514   int slack = 0;
   2515   Handle<DescriptorArray> descriptors = DescriptorArray::CopyForFastObjectClone(
   2516       isolate, source_descriptors, size, slack);
   2517   Handle<LayoutDescriptor> layout =
   2518       LayoutDescriptor::New(isolate, map, descriptors, size);
   2519   map->InitializeDescriptors(*descriptors, *layout);
   2520   map->CopyUnusedPropertyFieldsAdjustedForInstanceSize(*source_map);
   2521 
   2522   // Update bitfields
   2523   map->set_may_have_interesting_symbols(
   2524       source_map->may_have_interesting_symbols());
   2525 
   2526   return map;
   2527 }
   2528 
   2529 static MaybeHandle<JSObject> CloneObjectSlowPath(Isolate* isolate,
   2530                                                  Handle<HeapObject> source,
   2531                                                  int flags) {
   2532   Handle<JSObject> new_object;
   2533   if (flags & ObjectLiteral::kHasNullPrototype) {
   2534     new_object = isolate->factory()->NewJSObjectWithNullProto();
   2535   } else {
   2536     Handle<JSFunction> constructor(isolate->native_context()->object_function(),
   2537                                    isolate);
   2538     new_object = isolate->factory()->NewJSObject(constructor);
   2539   }
   2540 
   2541   if (source->IsNullOrUndefined()) {
   2542     return new_object;
   2543   }
   2544 
   2545   MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, new_object, source,
   2546                                                    nullptr, false),
   2547                MaybeHandle<JSObject>());
   2548   return new_object;
   2549 }
   2550 
   2551 RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) {
   2552   HandleScope scope(isolate);
   2553   DCHECK_EQ(4, args.length());
   2554   Handle<HeapObject> source = args.at<HeapObject>(0);
   2555   int flags = args.smi_at(1);
   2556 
   2557   MigrateDeprecated(source);
   2558 
   2559   FeedbackSlot slot = FeedbackVector::ToSlot(args.smi_at(2));
   2560   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
   2561 
   2562   FeedbackNexus nexus(vector, slot);
   2563   Handle<Map> source_map(source->map(), isolate);
   2564 
   2565   if (!CanFastCloneObject(source_map) || nexus.IsMegamorphic()) {
   2566     // Migrate to slow mode if needed.
   2567     nexus.ConfigureMegamorphic();
   2568     RETURN_RESULT_OR_FAILURE(isolate,
   2569                              CloneObjectSlowPath(isolate, source, flags));
   2570   }
   2571 
   2572   Handle<Map> result_map = FastCloneObjectMap(isolate, source, flags);
   2573   nexus.ConfigureCloneObject(source_map, result_map);
   2574 
   2575   return *result_map;
   2576 }
   2577 
   2578 RUNTIME_FUNCTION(Runtime_CloneObjectIC_Slow) {
   2579   HandleScope scope(isolate);
   2580   DCHECK_EQ(2, args.length());
   2581   Handle<HeapObject> source = args.at<HeapObject>(0);
   2582   int flags = args.smi_at(1);
   2583   RETURN_RESULT_OR_FAILURE(isolate,
   2584                            CloneObjectSlowPath(isolate, source, flags));
   2585 }
   2586 
   2587 RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
   2588   Handle<JSObject> receiver = args.at<JSObject>(0);
   2589   Handle<JSObject> holder = args.at<JSObject>(1);
   2590   Handle<AccessorInfo> info = args.at<AccessorInfo>(2);
   2591   Handle<Name> name = args.at<Name>(3);
   2592   Handle<Object> value = args.at(4);
   2593   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
   2594   HandleScope scope(isolate);
   2595 
   2596   if (V8_UNLIKELY(FLAG_runtime_stats)) {
   2597     RETURN_RESULT_OR_FAILURE(
   2598         isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
   2599                                             language_mode));
   2600   }
   2601 
   2602   DCHECK(info->IsCompatibleReceiver(*receiver));
   2603 
   2604   ShouldThrow should_throw =
   2605       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   2606   PropertyCallbackArguments arguments(isolate, info->data(), *receiver, *holder,
   2607                                       should_throw);
   2608   arguments.CallAccessorSetter(info, name, value);
   2609   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2610   return *value;
   2611 }
   2612 
   2613 RUNTIME_FUNCTION(Runtime_LoadCallbackProperty) {
   2614   Handle<JSObject> receiver = args.at<JSObject>(0);
   2615   Handle<JSObject> holder = args.at<JSObject>(1);
   2616   Handle<AccessorInfo> info = args.at<AccessorInfo>(2);
   2617   Handle<Name> name = args.at<Name>(3);
   2618   HandleScope scope(isolate);
   2619 
   2620   DCHECK(info->IsCompatibleReceiver(*receiver));
   2621 
   2622   PropertyCallbackArguments custom_args(isolate, info->data(), *receiver,
   2623                                         *holder, kThrowOnError);
   2624   Handle<Object> result = custom_args.CallAccessorGetter(info, name);
   2625   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2626   if (result.is_null()) return ReadOnlyRoots(isolate).undefined_value();
   2627   return *result;
   2628 }
   2629 
   2630 RUNTIME_FUNCTION(Runtime_LoadAccessorProperty) {
   2631   HandleScope scope(isolate);
   2632   DCHECK_EQ(args.length(), 3);
   2633   Handle<JSObject> receiver = args.at<JSObject>(0);
   2634   int handler_kind = args.smi_at(1);
   2635   Handle<CallHandlerInfo> call_handler_info = args.at<CallHandlerInfo>(2);
   2636 
   2637   Object* holder = *receiver;
   2638   if (handler_kind == LoadHandler::kApiGetterHolderIsPrototype) {
   2639     holder = receiver->map()->prototype();
   2640   } else {
   2641     DCHECK_EQ(handler_kind, LoadHandler::kApiGetter);
   2642   }
   2643 
   2644   // Call the accessor without additional arguments.
   2645   FunctionCallbackArguments custom(isolate, call_handler_info->data(),
   2646                                    *receiver, holder, nullptr, nullptr, 0);
   2647   Handle<Object> result_handle = custom.Call(*call_handler_info);
   2648   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2649   if (result_handle.is_null()) return ReadOnlyRoots(isolate).undefined_value();
   2650   return *result_handle;
   2651 }
   2652 
   2653 /**
   2654  * Loads a property with an interceptor performing post interceptor
   2655  * lookup if interceptor failed.
   2656  */
   2657 RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
   2658   HandleScope scope(isolate);
   2659   DCHECK_EQ(5, args.length());
   2660   Handle<Name> name = args.at<Name>(0);
   2661   Handle<Object> receiver = args.at(1);
   2662   Handle<JSObject> holder = args.at<JSObject>(2);
   2663 
   2664   if (!receiver->IsJSReceiver()) {
   2665     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
   2666         isolate, receiver, Object::ConvertReceiver(isolate, receiver));
   2667   }
   2668 
   2669   Handle<InterceptorInfo> interceptor(holder->GetNamedInterceptor(), isolate);
   2670   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
   2671                                       *holder, kDontThrow);
   2672   Handle<Object> result = arguments.CallNamedGetter(interceptor, name);
   2673 
   2674   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2675 
   2676   if (!result.is_null()) return *result;
   2677 
   2678   LookupIterator it(receiver, name, holder);
   2679   // Skip any lookup work until we hit the (possibly non-masking) interceptor.
   2680   while (it.state() != LookupIterator::INTERCEPTOR ||
   2681          !it.GetHolder<JSObject>().is_identical_to(holder)) {
   2682     DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
   2683     it.Next();
   2684   }
   2685   // Skip past the interceptor.
   2686   it.Next();
   2687   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
   2688 
   2689   if (it.IsFound()) return *result;
   2690 
   2691   Handle<Smi> slot = args.at<Smi>(3);
   2692   Handle<FeedbackVector> vector = args.at<FeedbackVector>(4);
   2693   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2694   FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
   2695   // It could actually be any kind of load IC slot here but the predicate
   2696   // handles all the cases properly.
   2697   if (!LoadIC::ShouldThrowReferenceError(slot_kind)) {
   2698     return ReadOnlyRoots(isolate).undefined_value();
   2699   }
   2700 
   2701   // Throw a reference error.
   2702   THROW_NEW_ERROR_RETURN_FAILURE(
   2703       isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
   2704 }
   2705 
   2706 
   2707 RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
   2708   HandleScope scope(isolate);
   2709   DCHECK_EQ(5, args.length());
   2710   // Runtime functions don't follow the IC's calling convention.
   2711   Handle<Object> value = args.at(0);
   2712   Handle<Smi> slot = args.at<Smi>(1);
   2713   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
   2714   Handle<JSObject> receiver = args.at<JSObject>(3);
   2715   Handle<Name> name = args.at<Name>(4);
   2716   FeedbackSlot vector_slot = FeedbackVector::ToSlot(slot->value());
   2717   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
   2718 
   2719   // TODO(ishell): Cache interceptor_holder in the store handler like we do
   2720   // for LoadHandler::kInterceptor case.
   2721   Handle<JSObject> interceptor_holder = receiver;
   2722   if (receiver->IsJSGlobalProxy()) {
   2723     FeedbackSlotKind kind = vector->GetKind(vector_slot);
   2724     if (IsStoreGlobalICKind(kind)) {
   2725       interceptor_holder = Handle<JSObject>::cast(isolate->global_object());
   2726     }
   2727   }
   2728   DCHECK(interceptor_holder->HasNamedInterceptor());
   2729   Handle<InterceptorInfo> interceptor(interceptor_holder->GetNamedInterceptor(),
   2730                                       isolate);
   2731 
   2732   DCHECK(!interceptor->non_masking());
   2733   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
   2734                                       *receiver, kDontThrow);
   2735 
   2736   Handle<Object> result = arguments.CallNamedSetter(interceptor, name, value);
   2737   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2738   if (!result.is_null()) return *value;
   2739 
   2740   LookupIterator it(receiver, name, receiver);
   2741   // Skip past any access check on the receiver.
   2742   if (it.state() == LookupIterator::ACCESS_CHECK) {
   2743     DCHECK(it.HasAccess());
   2744     it.Next();
   2745   }
   2746   // Skip past the interceptor on the receiver.
   2747   DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
   2748   it.Next();
   2749 
   2750   MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
   2751                                    JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
   2752                ReadOnlyRoots(isolate).exception());
   2753   return *value;
   2754 }
   2755 
   2756 
   2757 RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
   2758   // TODO(verwaest): This should probably get the holder and receiver as input.
   2759   HandleScope scope(isolate);
   2760   Handle<JSObject> receiver = args.at<JSObject>(0);
   2761   DCHECK_GE(args.smi_at(1), 0);
   2762   uint32_t index = args.smi_at(1);
   2763 
   2764   Handle<InterceptorInfo> interceptor(receiver->GetIndexedInterceptor(),
   2765                                       isolate);
   2766   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
   2767                                       *receiver, kDontThrow);
   2768   Handle<Object> result = arguments.CallIndexedGetter(interceptor, index);
   2769 
   2770   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
   2771 
   2772   if (result.is_null()) {
   2773     LookupIterator it(isolate, receiver, index, receiver);
   2774     DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
   2775     it.Next();
   2776     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
   2777                                        Object::GetProperty(&it));
   2778   }
   2779 
   2780   return *result;
   2781 }
   2782 }  // namespace internal
   2783 }  // namespace v8
   2784