LCOV - code coverage report
Current view: top level - src/ic - ic.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 927 1036 89.5 %
Date: 2017-10-20 Functions: 58 80 72.5 %

          Line data    Source code
       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.h"
      11             : #include "src/base/bits.h"
      12             : #include "src/conversions.h"
      13             : #include "src/execution.h"
      14             : #include "src/field-type.h"
      15             : #include "src/frames-inl.h"
      16             : #include "src/ic/call-optimization.h"
      17             : #include "src/ic/handler-compiler.h"
      18             : #include "src/ic/handler-configuration-inl.h"
      19             : #include "src/ic/ic-inl.h"
      20             : #include "src/ic/ic-stats.h"
      21             : #include "src/ic/stub-cache.h"
      22             : #include "src/isolate-inl.h"
      23             : #include "src/macro-assembler.h"
      24             : #include "src/prototype.h"
      25             : #include "src/runtime-profiler.h"
      26             : #include "src/runtime/runtime-utils.h"
      27             : #include "src/runtime/runtime.h"
      28             : #include "src/tracing/trace-event.h"
      29             : #include "src/tracing/tracing-category-observer.h"
      30             : 
      31             : namespace v8 {
      32             : namespace internal {
      33             : 
      34           0 : char IC::TransitionMarkFromState(IC::State state) {
      35           0 :   switch (state) {
      36             :     case UNINITIALIZED:
      37             :       return '0';
      38             :     case PREMONOMORPHIC:
      39           0 :       return '.';
      40             :     case MONOMORPHIC:
      41           0 :       return '1';
      42             :     case RECOMPUTE_HANDLER:
      43           0 :       return '^';
      44             :     case POLYMORPHIC:
      45           0 :       return 'P';
      46             :     case MEGAMORPHIC:
      47           0 :       return 'N';
      48             :     case GENERIC:
      49           0 :       return 'G';
      50             :   }
      51           0 :   UNREACHABLE();
      52             : }
      53             : 
      54             : 
      55           0 : const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
      56           0 :   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
      57           0 :   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
      58             :     return ".IGNORE_OOB";
      59             :   }
      60           0 :   if (IsGrowStoreMode(mode)) return ".GROW";
      61           0 :   return "";
      62             : }
      63             : 
      64             : #define TRACE_GENERIC_IC(reason) set_slow_stub_reason(reason);
      65             : 
      66     8315178 : void IC::TraceIC(const char* type, Handle<Object> name) {
      67     8315178 :   if (FLAG_ic_stats) {
      68     8315178 :     if (AddressIsDeoptimizedCode()) return;
      69           0 :     State new_state = nexus()->StateFromFeedback();
      70           0 :     TraceIC(type, name, state(), new_state);
      71             :   }
      72             : }
      73             : 
      74           0 : Address IC::GetAbstractPC(int* line, int* column) const {
      75           0 :   JavaScriptFrameIterator it(isolate());
      76             : 
      77             :   JavaScriptFrame* frame = it.frame();
      78             :   DCHECK(!frame->is_builtin());
      79           0 :   int position = frame->position();
      80             : 
      81           0 :   Object* maybe_script = frame->function()->shared()->script();
      82           0 :   if (maybe_script->IsScript()) {
      83             :     Handle<Script> script(Script::cast(maybe_script), isolate());
      84             :     Script::PositionInfo info;
      85           0 :     Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
      86           0 :     *line = info.line + 1;
      87           0 :     *column = info.column + 1;
      88             :   } else {
      89           0 :     *line = position;
      90           0 :     *column = -1;
      91             :   }
      92             : 
      93           0 :   if (frame->is_interpreted()) {
      94             :     InterpretedFrame* iframe = static_cast<InterpretedFrame*>(frame);
      95             :     Address bytecode_start =
      96           0 :         reinterpret_cast<Address>(iframe->GetBytecodeArray()) - kHeapObjectTag +
      97           0 :         BytecodeArray::kHeaderSize;
      98           0 :     return bytecode_start + iframe->GetBytecodeOffset();
      99             :   }
     100             : 
     101           0 :   return frame->pc();
     102             : }
     103             : 
     104           0 : void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
     105           0 :                  State new_state) {
     106           0 :   if (V8_LIKELY(!FLAG_ic_stats)) return;
     107             : 
     108             :   Map* map = nullptr;
     109           0 :   if (!receiver_map().is_null()) {
     110             :     map = *receiver_map();
     111             :   }
     112             : 
     113             :   const char* modifier = "";
     114           0 :   if (IsKeyedStoreIC()) {
     115             :     KeyedAccessStoreMode mode =
     116           0 :         casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
     117             :     modifier = GetTransitionMarkModifier(mode);
     118             :   }
     119             : 
     120           0 :   if (!(FLAG_ic_stats &
     121             :         v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
     122             :     int line;
     123             :     int column;
     124           0 :     Address pc = GetAbstractPC(&line, &column);
     125           0 :     LOG(isolate(), ICEvent(type, is_keyed(), pc, line, column, map, *name,
     126             :                            TransitionMarkFromState(old_state),
     127             :                            TransitionMarkFromState(new_state), modifier,
     128             :                            slow_stub_reason_));
     129             :     return;
     130             :   }
     131             : 
     132           0 :   ICStats::instance()->Begin();
     133             :   ICInfo& ic_info = ICStats::instance()->Current();
     134           0 :   ic_info.type = is_keyed() ? "Keyed" : "";
     135             :   ic_info.type += type;
     136             : 
     137             :   Object* maybe_function =
     138           0 :       Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
     139             :   DCHECK(maybe_function->IsJSFunction());
     140             :   JSFunction* function = JSFunction::cast(maybe_function);
     141             :   int code_offset = 0;
     142           0 :   if (function->IsInterpreted()) {
     143           0 :     code_offset = InterpretedFrame::GetBytecodeOffset(fp());
     144             :   } else {
     145             :     code_offset =
     146           0 :         static_cast<int>(pc() - function->code()->instruction_start());
     147             :   }
     148             :   JavaScriptFrame::CollectFunctionAndOffsetForICStats(
     149           0 :       function, function->abstract_code(), code_offset);
     150             : 
     151             :   // Reserve enough space for IC transition state, the longest length is 17.
     152           0 :   ic_info.state.reserve(17);
     153             :   ic_info.state = "(";
     154           0 :   ic_info.state += TransitionMarkFromState(old_state);
     155             :   ic_info.state += "->";
     156           0 :   ic_info.state += TransitionMarkFromState(new_state);
     157             :   ic_info.state += modifier;
     158             :   ic_info.state += ")";
     159           0 :   ic_info.map = reinterpret_cast<void*>(map);
     160           0 :   if (map != nullptr) {
     161           0 :     ic_info.is_dictionary_map = map->is_dictionary_map();
     162           0 :     ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors();
     163           0 :     ic_info.instance_type = std::to_string(map->instance_type());
     164             :   }
     165             :   // TODO(lpy) Add name as key field in ICStats.
     166           0 :   ICStats::instance()->End();
     167             : }
     168             : 
     169             : 
     170             : #define TRACE_IC(type, name) TraceIC(type, name)
     171             : 
     172     8598330 : IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
     173             :     : isolate_(isolate),
     174             :       vector_set_(false),
     175             :       kind_(FeedbackSlotKind::kInvalid),
     176             :       target_maps_set_(false),
     177             :       slow_stub_reason_(nullptr),
     178    17196660 :       nexus_(nexus) {
     179             :   // To improve the performance of the (much used) IC code, we unfold a few
     180             :   // levels of the stack frame iteration code. This yields a ~35% speedup when
     181             :   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
     182     8598330 :   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
     183             :   Address* constant_pool = nullptr;
     184             :   if (FLAG_enable_embedded_constant_pool) {
     185             :     constant_pool = reinterpret_cast<Address*>(
     186             :         entry + ExitFrameConstants::kConstantPoolOffset);
     187             :   }
     188             :   Address* pc_address =
     189     8598330 :       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
     190     8598330 :   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
     191             :   // If there's another JavaScript frame on the stack we need to look one frame
     192             :   // further down the stack to find the frame pointer and the return address
     193             :   // stack slot.
     194     8598330 :   if (depth == EXTRA_CALL_FRAME) {
     195             :     if (FLAG_enable_embedded_constant_pool) {
     196             :       constant_pool = reinterpret_cast<Address*>(
     197             :           fp + StandardFrameConstants::kConstantPoolOffset);
     198             :     }
     199             :     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
     200           0 :     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
     201           0 :     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
     202             :   }
     203             : #ifdef DEBUG
     204             :   StackFrameIterator it(isolate);
     205             :   for (int i = 0; i < depth + 1; i++) it.Advance();
     206             :   StackFrame* frame = it.frame();
     207             :   DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
     208             : #endif
     209             :   // For interpreted functions, some bytecode handlers construct a
     210             :   // frame. We have to skip the constructed frame to find the interpreted
     211             :   // function's frame. Check if the there is an additional frame, and if there
     212             :   // is skip this frame. However, the pc should not be updated. The call to
     213             :   // ICs happen from bytecode handlers.
     214             :   intptr_t frame_marker =
     215     8598330 :       Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset);
     216     8598330 :   if (frame_marker == StackFrame::TypeToMarker(StackFrame::STUB)) {
     217     7595658 :     fp = Memory::Address_at(fp + TypedFrameConstants::kCallerFPOffset);
     218             :   }
     219     8598330 :   fp_ = fp;
     220             :   if (FLAG_enable_embedded_constant_pool) {
     221             :     constant_pool_address_ = constant_pool;
     222             :   }
     223     8598330 :   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
     224             :   DCHECK_NOT_NULL(nexus);
     225     8598330 :   kind_ = nexus->kind();
     226     8598332 :   state_ = nexus->StateFromFeedback();
     227     8598330 :   old_state_ = state_;
     228     8598330 : }
     229             : 
     230    22453005 : JSFunction* IC::GetHostFunction() const {
     231             :   // Compute the JavaScript frame for the frame pointer of this IC
     232             :   // structure. We need this to be able to find the function
     233             :   // corresponding to the frame.
     234     5781683 :   StackFrameIterator it(isolate());
     235    22453006 :   while (it.frame()->fp() != this->fp()) it.Advance();
     236             :   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
     237             :   // Find the function on the stack and both the active code for the
     238             :   // function and the original code.
     239    11563366 :   return frame->function();
     240             : }
     241             : 
     242     7606773 : static void LookupForRead(LookupIterator* it) {
     243     7631814 :   for (; it->IsFound(); it->Next()) {
     244     3530805 :     switch (it->state()) {
     245             :       case LookupIterator::NOT_FOUND:
     246             :       case LookupIterator::TRANSITION:
     247           0 :         UNREACHABLE();
     248             :       case LookupIterator::JSPROXY:
     249             :         return;
     250             :       case LookupIterator::INTERCEPTOR: {
     251             :         // If there is a getter, return; otherwise loop to perform the lookup.
     252             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
     253        2204 :         if (!holder->GetNamedInterceptor()->getter()->IsUndefined(
     254        2204 :                 it->isolate())) {
     255             :           return;
     256             :         }
     257             :         break;
     258             :       }
     259             :       case LookupIterator::ACCESS_CHECK:
     260             :         // ICs know how to perform access checks on global proxies.
     261       27455 :         if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
     262             :           break;
     263             :         }
     264             :         return;
     265             :       case LookupIterator::ACCESSOR:
     266             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     267             :       case LookupIterator::DATA:
     268             :         return;
     269             :     }
     270             :   }
     271             : }
     272             : 
     273     1882794 : bool IC::ShouldRecomputeHandler(Handle<String> name) {
     274      635936 :   if (!RecomputeHandlerForName(name)) return false;
     275             : 
     276      623429 :   maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
     277             : 
     278             :   // This is a contextual access, always just update the handler and stay
     279             :   // monomorphic.
     280      623429 :   if (IsLoadGlobalIC()) return true;
     281             : 
     282             :   // The current map wasn't handled yet. There's no reason to stay monomorphic,
     283             :   // *unless* we're moving from a deprecated map to its replacement, or
     284             :   // to a more general elements kind.
     285             :   // TODO(verwaest): Check if the current map is actually what the old map
     286             :   // would transition to.
     287      622836 :   if (maybe_handler_.is_null()) {
     288      580875 :     if (!receiver_map()->IsJSObjectMap()) return false;
     289      571355 :     Map* first_map = FirstTargetMap();
     290      571355 :     if (first_map == nullptr) return false;
     291             :     Handle<Map> old_map(first_map);
     292      326617 :     if (old_map->is_deprecated()) return true;
     293             :     return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
     294      314688 :                                                receiver_map()->elements_kind());
     295             :   }
     296             : 
     297             :   return true;
     298             : }
     299             : 
     300      650679 : bool IC::RecomputeHandlerForName(Handle<Object> name) {
     301      635936 :   if (is_keyed()) {
     302             :     // Determine whether the failure is due to a name failure.
     303       14743 :     if (!name->IsName()) return false;
     304       14743 :     Name* stub_name = nexus()->FindFirstName();
     305       14743 :     if (*name != stub_name) return false;
     306             :   }
     307             : 
     308             :   return true;
     309             : }
     310             : 
     311             : 
     312    17307848 : void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
     313     8598331 :   update_receiver_map(receiver);
     314     8598329 :   if (!name->IsString()) return;
     315     8073446 :   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
     316      636071 :   if (receiver->IsNullOrUndefined(isolate())) return;
     317             : 
     318             :   // Remove the target from the code cache if it became invalid
     319             :   // because of changes in the prototype chain to avoid hitting it
     320             :   // again.
     321      635936 :   if (ShouldRecomputeHandler(Handle<String>::cast(name))) {
     322             :     MarkRecomputeHandler(name);
     323             :   }
     324             : }
     325             : 
     326             : 
     327        2129 : MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
     328        4258 :                                   Handle<Object> object, Handle<Object> key) {
     329             :   HandleScope scope(isolate());
     330        6387 :   THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
     331             : }
     332             : 
     333             : 
     334      386018 : MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
     335             :   HandleScope scope(isolate());
     336      579027 :   THROW_NEW_ERROR(
     337             :       isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
     338             : }
     339             : 
     340             : 
     341             : // static
     342    11477168 : void IC::OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
     343             :                            JSFunction* host_function) {
     344     5738584 :   if (FLAG_trace_opt_verbose) {
     345             :     // TODO(leszeks): The host function is only needed for this print, we could
     346             :     // remove it as a parameter if we're of with removing this trace (or only
     347             :     // tracing the feedback vector, not the function name).
     348           0 :     if (vector->profiler_ticks() != 0) {
     349           0 :       PrintF("[resetting ticks for ");
     350           0 :       host_function->PrintName();
     351           0 :       PrintF(" due from %d due to IC change]\n", vector->profiler_ticks());
     352             :     }
     353             :   }
     354             :   vector->set_profiler_ticks(0);
     355             :   isolate->runtime_profiler()->NotifyICChanged();
     356             :   // TODO(2029): When an optimized function is patched, it would
     357             :   // be nice to propagate the corresponding type information to its
     358             :   // unoptimized version for the benefit of later inlining.
     359     5738584 : }
     360             : 
     361     8695397 : static bool MigrateDeprecated(Handle<Object> object) {
     362     8695399 :   if (!object->IsJSObject()) return false;
     363             :   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
     364     8545863 :   if (!receiver->map()->is_deprecated()) return false;
     365        2937 :   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
     366        2937 :   return true;
     367             : }
     368             : 
     369    10928145 : void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
     370     3642715 :   if (new_state == PREMONOMORPHIC) {
     371     3552742 :     nexus()->ConfigurePremonomorphic();
     372       89973 :   } else if (new_state == MEGAMORPHIC) {
     373             :     DCHECK_IMPLIES(!is_keyed(), key->IsName());
     374      179946 :     nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
     375             :   } else {
     376           0 :     UNREACHABLE();
     377             :   }
     378             : 
     379     3642715 :   vector_set_ = true;
     380     7285430 :   OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
     381     3642715 : }
     382             : 
     383     1774908 : void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
     384     5324724 :                               Handle<Object> handler) {
     385     1774908 :   if (IsLoadGlobalIC()) {
     386             :     LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
     387       52292 :     nexus->ConfigureHandlerMode(handler);
     388             :   } else {
     389             :     // Non-keyed ICs don't track the name explicitly.
     390     1722616 :     if (!is_keyed()) name = Handle<Name>::null();
     391     1722616 :     nexus()->ConfigureMonomorphic(name, map, handler);
     392             :   }
     393             : 
     394     1774908 :   vector_set_ = true;
     395     3549816 :   OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
     396     1774908 : }
     397             : 
     398      289000 : void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
     399      578000 :                               ObjectHandles* handlers) {
     400             :   DCHECK(!IsLoadGlobalIC());
     401             :   // Non-keyed ICs don't track the name explicitly.
     402      289000 :   if (!is_keyed()) name = Handle<Name>::null();
     403      289000 :   nexus()->ConfigurePolymorphic(name, maps, handlers);
     404             : 
     405      289000 :   vector_set_ = true;
     406      578000 :   OnFeedbackChanged(isolate(), *vector(), GetHostFunction());
     407      289000 : }
     408             : 
     409     3790936 : MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
     410             :   // If the object is undefined or null it's illegal to try to get any
     411             :   // of its properties; throw a TypeError in that case.
     412    13076194 :   if (object->IsNullOrUndefined(isolate())) {
     413        4554 :     if (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
     414             :       // Ensure the IC state progresses.
     415         134 :       TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
     416         134 :       update_receiver_map(object);
     417         268 :       PatchCache(name, slow_stub());
     418         134 :       TRACE_IC("LoadIC", name);
     419             :     }
     420             : 
     421        2277 :     if (*name == isolate()->heap()->iterator_symbol()) {
     422         202 :       return Runtime::ThrowIteratorError(isolate(), object);
     423             :     }
     424        2075 :     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
     425             :   }
     426             : 
     427     3788660 :   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
     428             : 
     429     3788660 :   if (state() != UNINITIALIZED) {
     430     1608299 :     JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
     431     1608299 :     update_receiver_map(object);
     432             :   }
     433             :   // Named lookup in the object.
     434     3788660 :   LookupIterator it(object, name);
     435     3788662 :   LookupForRead(&it);
     436             : 
     437     4073764 :   if (it.IsFound() || !ShouldThrowReferenceError()) {
     438             :     // Update inline cache and stub cache.
     439     3596213 :     if (use_ic) UpdateCaches(&it);
     440             : 
     441             :     // Get the property.
     442             :     Handle<Object> result;
     443             : 
     444     7192421 :     ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
     445             :                                Object);
     446     3594777 :     if (it.IsFound()) {
     447     3501939 :       return result;
     448       92838 :     } else if (!ShouldThrowReferenceError()) {
     449       92808 :       LOG(isolate(), SuspectReadEvent(*name, *object));
     450       92808 :       return result;
     451             :     }
     452             :   }
     453      192479 :   return ReferenceError(name);
     454             : }
     455             : 
     456     1882871 : MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
     457     2031999 :   Handle<JSGlobalObject> global = isolate()->global_object();
     458             : 
     459     1882871 :   if (name->IsString()) {
     460             :     // Look up in script context table.
     461     1882871 :     Handle<String> str_name = Handle<String>::cast(name);
     462             :     Handle<ScriptContextTable> script_contexts(
     463             :         global->native_context()->script_context_table());
     464             : 
     465             :     ScriptContextTable::LookupResult lookup_result;
     466     1882871 :     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
     467             :       Handle<Object> result =
     468             :           FixedArray::get(*ScriptContextTable::GetContext(
     469       99762 :                               script_contexts, lookup_result.context_index),
     470       99762 :                           lookup_result.slot_index, isolate());
     471       49881 :       if (result->IsTheHole(isolate())) {
     472             :         // Do not install stubs and stay pre-monomorphic for
     473             :         // uninitialized accesses.
     474         515 :         return ReferenceError(name);
     475             :       }
     476             : 
     477       98732 :       if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
     478       49366 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
     479             :         LoadScriptContextFieldStub stub(isolate(), &lookup_result);
     480       98732 :         PatchCache(name, stub.GetCode());
     481       49366 :         TRACE_IC("LoadGlobalIC", name);
     482             :       }
     483       49366 :       return result;
     484             :     }
     485             :   }
     486     1832990 :   return LoadIC::Load(global, name);
     487             : }
     488             : 
     489       29218 : static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
     490             :                                        Handle<Map> new_receiver_map) {
     491             :   DCHECK(!new_receiver_map.is_null());
     492       98532 :   for (Handle<Map> map : *receiver_maps) {
     493       94516 :     if (!map.is_null() && map.is_identical_to(new_receiver_map)) {
     494             :       return false;
     495             :     }
     496             :   }
     497       22056 :   receiver_maps->push_back(new_receiver_map);
     498       22056 :   return true;
     499             : }
     500             : 
     501     1332600 : bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
     502             :   DCHECK(IsHandler(*handler));
     503      570064 :   if (is_keyed() && state() != RECOMPUTE_HANDLER) {
     504       35428 :     if (nexus()->FindFirstName() != *name) return false;
     505             :   }
     506      539809 :   Handle<Map> map = receiver_map();
     507             :   MapHandles maps;
     508             :   ObjectHandles handlers;
     509             : 
     510      539809 :   TargetMaps(&maps);
     511     1079620 :   int number_of_maps = static_cast<int>(maps.size());
     512             :   int deprecated_maps = 0;
     513             :   int handler_to_overwrite = -1;
     514      539810 :   if (!nexus()->FindHandlers(&handlers, number_of_maps)) return false;
     515             : 
     516      564057 :   for (int i = 0; i < number_of_maps; i++) {
     517     1128236 :     Handle<Map> current_map = maps.at(i);
     518      564118 :     if (current_map->is_deprecated()) {
     519             :       // Filter out deprecated maps to ensure their instances get migrated.
     520       12628 :       ++deprecated_maps;
     521      551490 :     } else if (map.is_identical_to(current_map)) {
     522             :       // If both map and handler stayed the same (and the name is also the
     523             :       // same as checked above, for keyed accesses), we're not progressing
     524             :       // in the lattice and need to go MEGAMORPHIC instead. There's one
     525             :       // exception to this rule, which is when we're in RECOMPUTE_HANDLER
     526             :       // state, there we allow to migrate to a new handler.
     527       58104 :       if (handler.is_identical_to(handlers[i]) &&
     528             :           state() != RECOMPUTE_HANDLER) {
     529             :         return false;
     530             :       }
     531             :       // If the receiver type is already in the polymorphic IC, this indicates
     532             :       // there was a prototoype chain failure. In that case, just overwrite the
     533             :       // handler.
     534             :       handler_to_overwrite = i;
     535     1044848 :     } else if (handler_to_overwrite == -1 &&
     536      521704 :                IsTransitionOfMonomorphicTarget(*current_map, *map)) {
     537             :       handler_to_overwrite = i;
     538             :     }
     539             :   }
     540             : 
     541             :   int number_of_valid_maps =
     542      539749 :       number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
     543             : 
     544      539749 :   if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false;
     545      711063 :   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
     546             :     return false;
     547             :   }
     548             : 
     549             :   number_of_valid_maps++;
     550      511736 :   if (number_of_valid_maps == 1) {
     551      241927 :     ConfigureVectorState(name, receiver_map(), handler);
     552             :   } else {
     553      278355 :     if (is_keyed() && nexus()->FindFirstName() != *name) return false;
     554      269809 :     if (handler_to_overwrite >= 0) {
     555        4350 :       handlers[handler_to_overwrite] = handler;
     556        2175 :       if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
     557        1257 :         maps[handler_to_overwrite] = map;
     558             :       }
     559             :     } else {
     560      267634 :       maps.push_back(map);
     561      267634 :       handlers.push_back(handler);
     562             :     }
     563             : 
     564      269809 :     ConfigureVectorState(name, maps, &handlers);
     565             :   }
     566             : 
     567             :   return true;
     568             : }
     569             : 
     570           0 : void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
     571             :   DCHECK(IsHandler(*handler));
     572     1233812 :   ConfigureVectorState(name, receiver_map(), handler);
     573           0 : }
     574             : 
     575             : 
     576       54506 : void IC::CopyICToMegamorphicCache(Handle<Name> name) {
     577             :   MapHandles maps;
     578             :   ObjectHandles handlers;
     579       27253 :   TargetMaps(&maps);
     580       81759 :   if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return;
     581      245601 :   for (int i = 0; i < static_cast<int>(maps.size()); i++) {
     582      218348 :     UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
     583             :   }
     584             : }
     585             : 
     586             : 
     587      530652 : bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
     588      530652 :   if (source_map == nullptr) return true;
     589      530652 :   if (target_map == nullptr) return false;
     590      530652 :   if (source_map->is_abandoned_prototype_map()) return false;
     591             :   ElementsKind target_elements_kind = target_map->elements_kind();
     592             :   bool more_general_transition = IsMoreGeneralElementsKindTransition(
     593      489658 :       source_map->elements_kind(), target_elements_kind);
     594             :   Map* transitioned_map = nullptr;
     595      489658 :   if (more_general_transition) {
     596             :     MapHandles map_list;
     597       35232 :     map_list.push_back(handle(target_map));
     598       17616 :     transitioned_map = source_map->FindElementsKindTransitionedMap(map_list);
     599             :   }
     600      489658 :   return transitioned_map == target_map;
     601             : }
     602             : 
     603     2882302 : void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
     604             :   DCHECK(IsHandler(*handler));
     605             :   // Currently only load and store ICs support non-code handlers.
     606             :   DCHECK(IsAnyLoad() || IsAnyStore());
     607     2494837 :   switch (state()) {
     608             :     case UNINITIALIZED:
     609             :     case PREMONOMORPHIC:
     610             :       UpdateMonomorphicIC(handler, name);
     611             :       break;
     612             :     case RECOMPUTE_HANDLER:
     613             :     case MONOMORPHIC:
     614      374299 :       if (IsLoadGlobalIC()) {
     615             :         UpdateMonomorphicIC(handler, name);
     616             :         break;
     617             :       }
     618             :     // Fall through.
     619             :     case POLYMORPHIC:
     620      552155 :       if (UpdatePolymorphicIC(name, handler)) break;
     621       53585 :       if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
     622       27253 :         CopyICToMegamorphicCache(name);
     623             :       }
     624       40419 :       ConfigureVectorState(MEGAMORPHIC, name);
     625             :     // Fall through.
     626             :     case MEGAMORPHIC:
     627      749291 :       UpdateMegamorphicCache(*receiver_map(), *name, *handler);
     628             :       // Indicate that we've handled this case.
     629      749291 :       vector_set_ = true;
     630      749291 :       break;
     631             :     case GENERIC:
     632           0 :       UNREACHABLE();
     633             :       break;
     634             :   }
     635     2494837 : }
     636             : 
     637      780823 : Handle<Smi> LoadIC::SimpleFieldLoad(Isolate* isolate, FieldIndex index) {
     638      780823 :   TRACE_HANDLER_STATS(isolate, LoadIC_LoadFieldDH);
     639      780823 :   return LoadHandler::LoadField(isolate, index);
     640             : }
     641             : 
     642     8479877 : void LoadIC::UpdateCaches(LookupIterator* lookup) {
     643    10546145 :   if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
     644             :     // This is the first time we execute this inline cache. Set the target to
     645             :     // the pre monomorphic stub to delay setting the monomorphic state.
     646      346862 :     TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
     647      346862 :     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
     648      346862 :     TRACE_IC("LoadIC", lookup->name());
     649     2331186 :     return;
     650             :   }
     651             : 
     652             :   Handle<Object> code;
     653     3246741 :   if (lookup->state() == LookupIterator::ACCESS_CHECK) {
     654          58 :     code = slow_stub();
     655     3246683 :   } else if (!lookup->IsFound()) {
     656       81499 :     TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
     657       81499 :     Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
     658             :     code = LoadHandler::LoadFullChain(isolate(), receiver_map(),
     659             :                                       isolate()->factory()->null_value(),
     660       81499 :                                       lookup->name(), smi_handler);
     661             :   } else {
     662     3165184 :     if (IsLoadGlobalIC()) {
     663     1639533 :       if (lookup->TryLookupCachedProperty()) {
     664             :         DCHECK_EQ(LookupIterator::DATA, lookup->state());
     665             :       }
     666     3277471 :       if (lookup->state() == LookupIterator::DATA &&
     667             :           lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
     668             :         DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
     669             :         // Now update the cell in the feedback vector.
     670             :         LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
     671     1637462 :         nexus->ConfigurePropertyCellMode(lookup->GetPropertyCell());
     672     1637463 :         TRACE_IC("LoadGlobalIC", lookup->name());
     673     1637462 :         return;
     674             :       }
     675             :     }
     676     1527722 :     code = ComputeHandler(lookup);
     677             :   }
     678             : 
     679     1609278 :   PatchCache(lookup->name(), code);
     680     1609278 :   TRACE_IC("LoadIC", lookup->name());
     681             : }
     682             : 
     683      858465 : StubCache* IC::stub_cache() {
     684      858465 :   if (IsAnyLoad()) {
     685      430785 :     return isolate()->load_stub_cache();
     686             :   } else {
     687             :     DCHECK(IsAnyStore());
     688      427680 :     return isolate()->store_stub_cache();
     689             :   }
     690             : }
     691             : 
     692      858465 : void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) {
     693      858465 :   stub_cache()->Set(name, map, handler);
     694      858465 : }
     695             : 
     696           0 : void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
     697             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
     698           0 :   if (V8_LIKELY(!FLAG_runtime_stats)) return;
     699           0 :   if (IsAnyLoad()) {
     700           0 :     TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor);
     701             :   } else {
     702             :     DCHECK(IsAnyStore());
     703           0 :     TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor);
     704             :   }
     705             : }
     706             : 
     707     2232199 : Handle<Object> IC::ComputeHandler(LookupIterator* lookup) {
     708             :   // Try to find a globally shared handler stub.
     709     2232199 :   Handle<Object> shared_handler = GetMapIndependentHandler(lookup);
     710     2232196 :   if (!shared_handler.is_null()) {
     711             :     DCHECK(IC::IsHandler(*shared_handler));
     712     1986497 :     return shared_handler;
     713             :   }
     714             : 
     715      245699 :   return CompileHandler(lookup);
     716             : }
     717             : 
     718     2904059 : Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
     719             :   Handle<Object> receiver = lookup->GetReceiver();
     720     1566551 :   if (receiver->IsString() &&
     721     2288587 :       *lookup->name() == isolate()->heap()->length_string()) {
     722       11062 :     FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
     723       11062 :     return SimpleFieldLoad(isolate(), index);
     724             :   }
     725             : 
     726     1518873 :   if (receiver->IsStringWrapper() &&
     727        2191 :       *lookup->name() == isolate()->heap()->length_string()) {
     728         169 :     TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
     729         169 :     return BUILTIN_CODE(isolate(), LoadIC_StringLength);
     730             :   }
     731             : 
     732             :   // Use specialized code for getting prototype of functions.
     733     1721385 :   if (receiver->IsJSFunction() &&
     734      346429 :       *lookup->name() == isolate()->heap()->prototype_string() &&
     735     1799614 :       JSFunction::cast(*receiver)->has_prototype_slot() &&
     736             :       !JSFunction::cast(*receiver)->map()->has_non_instance_prototype()) {
     737             :     Handle<Code> stub;
     738      140197 :     TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
     739      140197 :     return BUILTIN_CODE(isolate(), LoadIC_FunctionPrototype);
     740             :   }
     741             : 
     742     1376315 :   Handle<Map> map = receiver_map();
     743             :   Handle<JSObject> holder;
     744             :   bool receiver_is_holder;
     745     1376315 :   if (lookup->state() != LookupIterator::JSPROXY) {
     746             :     holder = lookup->GetHolder<JSObject>();
     747             :     receiver_is_holder = receiver.is_identical_to(holder);
     748             :   }
     749             : 
     750     1376315 :   switch (lookup->state()) {
     751             :     case LookupIterator::INTERCEPTOR: {
     752         990 :       Handle<Smi> smi_handler = LoadHandler::LoadInterceptor(isolate());
     753             : 
     754        1980 :       if (holder->GetNamedInterceptor()->non_masking()) {
     755             :         Handle<Object> holder_ref = isolate()->factory()->null_value();
     756          84 :         if (!receiver_is_holder || IsLoadGlobalIC()) {
     757          24 :           holder_ref = Map::GetOrCreatePrototypeWeakCell(holder, isolate());
     758             :         }
     759          54 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonMaskingInterceptorDH);
     760             :         return LoadHandler::LoadFullChain(isolate(), map, holder_ref,
     761          54 :                                           lookup->name(), smi_handler);
     762             :       }
     763             : 
     764         936 :       if (receiver_is_holder) {
     765             :         DCHECK(map->has_named_interceptor());
     766         763 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorDH);
     767         763 :         return smi_handler;
     768             :       }
     769             : 
     770         173 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorFromPrototypeDH);
     771             :       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
     772         173 :                                             lookup->name(), smi_handler);
     773             :     }
     774             : 
     775             :     case LookupIterator::ACCESSOR: {
     776             :       // Use simple field loads for some well-known callback properties.
     777             :       // The method will only return true for absolute truths based on the
     778             :       // receiver maps.
     779             :       int object_offset;
     780      192101 :       if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
     781             :                                              &object_offset)) {
     782      179294 :         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
     783       89647 :         return SimpleFieldLoad(isolate(), index);
     784             :       }
     785      102454 :       if (holder->IsJSModuleNamespace()) {
     786             :         Handle<ObjectHashTable> exports(
     787             :             Handle<JSModuleNamespace>::cast(holder)->module()->exports(),
     788             :             isolate());
     789             :         int entry = exports->FindEntry(isolate(), lookup->name(),
     790       39608 :                                        Smi::ToInt(lookup->name()->GetHash()));
     791             :         // We found the accessor, so the entry must exist.
     792             :         DCHECK_NE(entry, ObjectHashTable::kNotFound);
     793             :         int index = ObjectHashTable::EntryToValueIndex(entry);
     794       19804 :         return LoadHandler::LoadModuleExport(isolate(), index);
     795             :       }
     796             : 
     797       82650 :       Handle<Object> accessors = lookup->GetAccessors();
     798       82650 :       if (accessors->IsAccessorPair()) {
     799       75083 :         if (lookup->TryLookupCachedProperty()) {
     800             :           DCHECK_EQ(LookupIterator::DATA, lookup->state());
     801       71594 :           return ComputeHandler(lookup);
     802             :         }
     803             : 
     804             :         // When debugging we need to go the slow path to flood the accessor.
     805      150120 :         if (GetHostFunction()->shared()->HasBreakInfo()) {
     806          14 :           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
     807          14 :           return slow_stub();
     808             :         }
     809             : 
     810             :         Handle<Object> getter(AccessorPair::cast(*accessors)->getter(),
     811             :                               isolate());
     812       75641 :         if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
     813         350 :           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
     814         350 :           return slow_stub();
     815             :         }
     816             : 
     817       74696 :         CallOptimization call_optimization(getter);
     818       74696 :         if (call_optimization.is_simple_api_call()) {
     819        7109 :           if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
     820        3528 :               !holder->HasFastProperties()) {
     821          69 :             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
     822          69 :             return slow_stub();
     823             :           }
     824        3512 :           break;
     825             :         }
     826             : 
     827             :         // FunctionTemplate isn't yet supported as smi-handler.
     828       71115 :         if (getter->IsFunctionTemplateInfo()) {
     829           0 :           if (!holder->HasFastProperties()) {
     830           0 :             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
     831           0 :             return slow_stub();
     832             :           }
     833             :           break;
     834             :         }
     835             : 
     836             :         Handle<Smi> smi_handler;
     837       71115 :         if (holder->HasFastProperties()) {
     838             :           smi_handler =
     839      128416 :               LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
     840             : 
     841       64208 :           if (receiver_is_holder) {
     842       14937 :             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
     843       14937 :             return smi_handler;
     844             :           }
     845       49271 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorFromPrototypeDH);
     846        6907 :         } else if (holder->IsJSGlobalObject()) {
     847         654 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
     848         654 :           smi_handler = LoadHandler::LoadGlobal(isolate());
     849             :         } else {
     850        6253 :           smi_handler = LoadHandler::LoadNormal(isolate());
     851             : 
     852        6253 :           if (receiver_is_holder) {
     853        6198 :             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
     854        6198 :             return smi_handler;
     855             :           }
     856          55 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
     857             :         }
     858             : 
     859             :         return LoadHandler::LoadFromPrototype(isolate(), map, holder,
     860       49980 :                                               lookup->name(), smi_handler);
     861             :       }
     862             : 
     863             :       Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
     864             : 
     865       15122 :       if (v8::ToCData<Address>(info->getter()) == nullptr ||
     866       15098 :           !AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map) ||
     867       22009 :           !holder->HasFastProperties() ||
     868         448 :           (info->is_sloppy() && !receiver->IsJSReceiver())) {
     869         668 :         TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
     870         668 :         return slow_stub();
     871             :       }
     872             : 
     873             :       Handle<Smi> smi_handler =
     874       13798 :           LoadHandler::LoadApiGetter(isolate(), lookup->GetAccessorIndex());
     875        6899 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH);
     876        6899 :       if (receiver_is_holder) return smi_handler;
     877         334 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
     878             :       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
     879         334 :                                             lookup->name(), smi_handler);
     880             :     }
     881             : 
     882             :     case LookupIterator::DATA: {
     883             :       DCHECK_EQ(kData, lookup->property_details().kind());
     884             :       Handle<Smi> smi_handler;
     885     1179123 :       if (lookup->is_dictionary_holder()) {
     886       26590 :         smi_handler = LoadHandler::LoadNormal(isolate());
     887       26590 :         if (receiver_is_holder) {
     888       11197 :           if (holder->IsJSGlobalObject()) {
     889             :             // TODO(verwaest): This is a workaround for code that leaks the
     890             :             // global object.
     891           0 :             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalDH);
     892           0 :             smi_handler = LoadHandler::LoadGlobal(isolate());
     893             :             return LoadHandler::LoadFromPrototype(isolate(), map, holder,
     894           0 :                                                   lookup->name(), smi_handler);
     895             :           }
     896             :           DCHECK(!holder->IsJSGlobalObject());
     897       11197 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
     898       11197 :           return smi_handler;
     899             :         }
     900             : 
     901       15393 :         if (holder->IsJSGlobalObject()) {
     902       11599 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
     903       11599 :           smi_handler = LoadHandler::LoadGlobal(isolate());
     904             :         } else {
     905        3794 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
     906             :         }
     907             : 
     908     1152533 :       } else if (lookup->property_details().location() == kField) {
     909      680113 :         FieldIndex field = lookup->GetFieldIndex();
     910      680114 :         smi_handler = SimpleFieldLoad(isolate(), field);
     911      680113 :         if (receiver_is_holder) return smi_handler;
     912       19800 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
     913             :       } else {
     914             :         DCHECK_EQ(kDescriptor, lookup->property_details().location());
     915             :         smi_handler =
     916      944840 :             LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
     917      472420 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
     918      472420 :         if (receiver_is_holder) return smi_handler;
     919      298811 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
     920             :       }
     921             :       return LoadHandler::LoadFromPrototype(isolate(), map, holder,
     922      334004 :                                             lookup->name(), smi_handler);
     923             :     }
     924             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
     925          36 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadIntegerIndexedExoticDH);
     926          36 :       return LoadHandler::LoadNonExistent(isolate());
     927             :     case LookupIterator::JSPROXY: {
     928             :       Handle<JSProxy> holder_proxy = lookup->GetHolder<JSProxy>();
     929             :       bool receiver_is_holder_proxy = receiver.is_identical_to(holder_proxy);
     930        4066 :       Handle<Smi> smi_handler = LoadHandler::LoadProxy(isolate());
     931        4066 :       if (receiver_is_holder_proxy) {
     932        2896 :         return smi_handler;
     933             :       }
     934             :       return LoadHandler::LoadFromPrototype(isolate(), map, holder_proxy,
     935        1170 :                                             lookup->name(), smi_handler);
     936             :     }
     937             :     case LookupIterator::ACCESS_CHECK:
     938             :     case LookupIterator::NOT_FOUND:
     939             :     case LookupIterator::TRANSITION:
     940           0 :       UNREACHABLE();
     941             :   }
     942             : 
     943        3512 :   return Handle<Code>::null();
     944             : }
     945             : 
     946        3512 : Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup) {
     947             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
     948             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
     949        7024 :   Handle<Map> map = receiver_map();
     950             : 
     951        3512 :   Handle<Object> accessors = lookup->GetAccessors();
     952             :   DCHECK(accessors->IsAccessorPair());
     953             :   DCHECK(holder->HasFastProperties());
     954             :   DCHECK(!GetHostFunction()->shared()->HasBreakInfo());
     955             :   Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
     956             :                         isolate());
     957        3512 :   CallOptimization call_optimization(getter);
     958             :   NamedLoadHandlerCompiler compiler(isolate(), map, holder);
     959             :   DCHECK(call_optimization.is_simple_api_call());
     960        3512 :   TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
     961        3512 :   int index = lookup->GetAccessorIndex();
     962             :   Handle<Code> code = compiler.CompileLoadCallback(
     963        3512 :       lookup->name(), call_optimization, index, slow_stub());
     964        7024 :   return code;
     965             : }
     966             : 
     967             : 
     968      601654 : static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
     969             :   // This helper implements a few common fast cases for converting
     970             :   // non-smi keys of keyed loads/stores to a smi or a string.
     971      601654 :   if (key->IsHeapNumber()) {
     972             :     double value = Handle<HeapNumber>::cast(key)->value();
     973        2055 :     if (std::isnan(value)) {
     974             :       key = isolate->factory()->NaN_string();
     975             :     } else {
     976             :       int int_value = FastD2I(value);
     977        1832 :       if (value == int_value && Smi::IsValid(int_value)) {
     978             :         key = handle(Smi::FromInt(int_value), isolate);
     979             :       }
     980             :     }
     981      599599 :   } else if (key->IsUndefined(isolate)) {
     982             :     key = isolate->factory()->undefined_string();
     983      592992 :   } else if (key->IsString()) {
     984       90168 :     key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
     985             :   }
     986      601654 :   return key;
     987             : }
     988             : 
     989      176419 : void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
     990      199131 :   Handle<Map> receiver_map(receiver->map(), isolate());
     991             :   DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE);  // Checked by caller.
     992             :   MapHandles target_receiver_maps;
     993      176419 :   TargetMaps(&target_receiver_maps);
     994             : 
     995      176419 :   if (target_receiver_maps.empty()) {
     996      153622 :     Handle<Object> handler = LoadElementHandler(receiver_map);
     997      153622 :     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
     998             :   }
     999             : 
    1000       93326 :   for (Handle<Map> map : target_receiver_maps) {
    1001       35307 :     if (map.is_null()) continue;
    1002       35307 :     if (map->instance_type() == JS_VALUE_TYPE) {
    1003             :       TRACE_GENERIC_IC("JSValue");
    1004             :       return;
    1005             :     }
    1006       35297 :     if (map->instance_type() == JS_PROXY_TYPE) {
    1007             :       TRACE_GENERIC_IC("JSProxy");
    1008             :       return;
    1009             :     }
    1010             :   }
    1011             : 
    1012             :   // The first time a receiver is seen that is a transitioned version of the
    1013             :   // previous monomorphic receiver type, assume the new ElementsKind is the
    1014             :   // monomorphic type. This benefits global arrays that only transition
    1015             :   // once, and all call sites accessing them are faster if they remain
    1016             :   // monomorphic. If this optimistic assumption is not true, the IC will
    1017             :   // miss again and it will become polymorphic and support both the
    1018             :   // untransitioned and transitioned maps.
    1019       54479 :   if (state() == MONOMORPHIC && !receiver->IsString() &&
    1020       38478 :       !receiver->IsJSProxy() &&
    1021             :       IsMoreGeneralElementsKindTransition(
    1022             :           target_receiver_maps.at(0)->elements_kind(),
    1023       15766 :           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
    1024        3339 :     Handle<Object> handler = LoadElementHandler(receiver_map);
    1025        3339 :     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
    1026             :   }
    1027             : 
    1028             :   DCHECK(state() != GENERIC);
    1029             : 
    1030             :   // Determine the list of receiver maps that this call site has seen,
    1031             :   // adding the map that was just encountered.
    1032       19373 :   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
    1033             :     // If the miss wasn't due to an unseen map, a polymorphic stub
    1034             :     // won't help, use the generic stub.
    1035             :     TRACE_GENERIC_IC("same map added twice");
    1036             :     return;
    1037             :   }
    1038             : 
    1039             :   // If the maximum number of receiver maps has been exceeded, use the generic
    1040             :   // version of the IC.
    1041       29420 :   if (target_receiver_maps.size() > kMaxKeyedPolymorphism) {
    1042             :     TRACE_GENERIC_IC("max polymorph exceeded");
    1043             :     return;
    1044             :   }
    1045             : 
    1046             :   ObjectHandles handlers;
    1047       12907 :   handlers.reserve(target_receiver_maps.size());
    1048       12907 :   LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers);
    1049             :   DCHECK_LE(1, target_receiver_maps.size());
    1050       25814 :   if (target_receiver_maps.size() == 1) {
    1051          40 :     ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
    1052             :   } else {
    1053       12887 :     ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
    1054             :   }
    1055             : }
    1056             : 
    1057      189097 : Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
    1058      189204 :   if (receiver_map->has_indexed_interceptor() &&
    1059             :       !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
    1060      399587 :           isolate()) &&
    1061             :       !receiver_map->GetIndexedInterceptor()->non_masking()) {
    1062          83 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
    1063          83 :     return LoadIndexedInterceptorStub(isolate()).GetCode();
    1064             :   }
    1065      189014 :   if (receiver_map->IsStringMap()) {
    1066        1161 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringStub);
    1067        1161 :     return BUILTIN_CODE(isolate(), KeyedLoadIC_IndexedString);
    1068             :   }
    1069             :   InstanceType instance_type = receiver_map->instance_type();
    1070      187853 :   if (instance_type < FIRST_JS_RECEIVER_TYPE) {
    1071          30 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
    1072          30 :     return BUILTIN_CODE(isolate(), KeyedLoadIC_Slow);
    1073             :   }
    1074      187823 :   if (instance_type == JS_PROXY_TYPE) {
    1075         178 :     return LoadHandler::LoadProxy(isolate());
    1076             :   }
    1077             : 
    1078             :   ElementsKind elements_kind = receiver_map->elements_kind();
    1079      187645 :   if (IsSloppyArgumentsElementsKind(elements_kind)) {
    1080        1826 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
    1081        1826 :     return KeyedLoadSloppyArgumentsStub(isolate()).GetCode();
    1082             :   }
    1083      185819 :   bool is_js_array = instance_type == JS_ARRAY_TYPE;
    1084      185819 :   if (elements_kind == DICTIONARY_ELEMENTS) {
    1085        7624 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
    1086             :     return LoadHandler::LoadElement(isolate(), elements_kind, false,
    1087       15248 :                                     is_js_array);
    1088             :   }
    1089             :   DCHECK(IsFastElementsKind(elements_kind) ||
    1090             :          IsFixedTypedArrayElementsKind(elements_kind));
    1091             :   // TODO(jkummerow): Use IsHoleyOrDictionaryElementsKind(elements_kind).
    1092             :   bool convert_hole_to_undefined =
    1093      199505 :       is_js_array && elements_kind == HOLEY_ELEMENTS &&
    1094             :       *receiver_map ==
    1095       21310 :           isolate()->raw_native_context()->GetInitialJSArrayMap(elements_kind);
    1096      178195 :   TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
    1097             :   return LoadHandler::LoadElement(isolate(), elements_kind,
    1098      356390 :                                   convert_hole_to_undefined, is_js_array);
    1099             : }
    1100             : 
    1101       12907 : void KeyedLoadIC::LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
    1102             :                                                  ObjectHandles* handlers) {
    1103             :   // Filter out deprecated maps to ensure their instances get migrated.
    1104             :   receiver_maps->erase(
    1105             :       std::remove_if(
    1106             :           receiver_maps->begin(), receiver_maps->end(),
    1107             :           [](const Handle<Map>& map) { return map->is_deprecated(); }),
    1108       12907 :       receiver_maps->end());
    1109             : 
    1110       57950 :   for (Handle<Map> receiver_map : *receiver_maps) {
    1111             :     // Mark all stable receiver maps that have elements kind transition map
    1112             :     // among receiver_maps as unstable because the optimizing compilers may
    1113             :     // generate an elements kind transition for this kind of receivers.
    1114       32136 :     if (receiver_map->is_stable()) {
    1115       20390 :       Map* tmap = receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
    1116       20390 :       if (tmap != nullptr) {
    1117          20 :         receiver_map->NotifyLeafMapLayoutChange();
    1118             :       }
    1119             :     }
    1120       64272 :     handlers->push_back(LoadElementHandler(receiver_map));
    1121             :   }
    1122       12907 : }
    1123             : 
    1124      280851 : MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
    1125             :                                       Handle<Object> key) {
    1126      280851 :   if (MigrateDeprecated(object)) {
    1127             :     Handle<Object> result;
    1128      640627 :     ASSIGN_RETURN_ON_EXCEPTION(
    1129             :         isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
    1130             :         Object);
    1131          22 :     return result;
    1132             :   }
    1133             : 
    1134             :   Handle<Object> load_handle;
    1135             : 
    1136             :   // Check for non-string values that can be converted into an
    1137             :   // internalized string directly or is representable as a smi.
    1138      280829 :   key = TryConvertKey(key, isolate());
    1139             : 
    1140             :   uint32_t index;
    1141      352688 :   if ((key->IsInternalizedString() &&
    1142      566558 :        !String::cast(*key)->AsArrayIndex(&index)) ||
    1143             :       key->IsSymbol()) {
    1144      194988 :     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
    1145             :                                LoadIC::Load(object, Handle<Name>::cast(key)),
    1146             :                                Object);
    1147      549884 :   } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
    1148             :              !object->IsJSValue()) {
    1149      553121 :     if ((object->IsJSReceiver() && key->IsSmi()) ||
    1150        1327 :         (object->IsString() && key->IsNumber())) {
    1151      176419 :       UpdateLoadElement(Handle<HeapObject>::cast(object));
    1152      176419 :       if (is_vector_set()) {
    1153      169868 :         TRACE_IC("LoadIC", key);
    1154             :       }
    1155             :     }
    1156             :   }
    1157             : 
    1158      280497 :   if (vector_needs_update()) {
    1159       13467 :     ConfigureVectorState(MEGAMORPHIC, key);
    1160       13467 :     TRACE_IC("LoadIC", key);
    1161             :   }
    1162             : 
    1163      280497 :   if (!load_handle.is_null()) return load_handle;
    1164             : 
    1165             :   Handle<Object> result;
    1166      366670 :   ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    1167             :                              Runtime::GetObjectProperty(isolate(), object, key),
    1168             :                              Object);
    1169      182935 :   return result;
    1170             : }
    1171             : 
    1172             : 
    1173     2194471 : bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
    1174             :                              JSReceiver::StoreFromKeyed store_mode) {
    1175             :   // Disable ICs for non-JSObjects for now.
    1176             :   Handle<Object> object = it->GetReceiver();
    1177     1095744 :   if (object->IsJSProxy()) return true;
    1178     1095608 :   if (!object->IsJSObject()) return false;
    1179             :   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    1180             :   DCHECK(!receiver->map()->is_deprecated());
    1181             : 
    1182     1100668 :   for (; it->IsFound(); it->Next()) {
    1183      604734 :     switch (it->state()) {
    1184             :       case LookupIterator::NOT_FOUND:
    1185             :       case LookupIterator::TRANSITION:
    1186           0 :         UNREACHABLE();
    1187             :       case LookupIterator::JSPROXY:
    1188             :         return true;
    1189             :       case LookupIterator::INTERCEPTOR: {
    1190             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
    1191         179 :         InterceptorInfo* info = holder->GetNamedInterceptor();
    1192         179 :         if (it->HolderIsReceiverOrHiddenPrototype()) {
    1193         447 :           return !info->non_masking() && receiver.is_identical_to(holder) &&
    1194         149 :                  !info->setter()->IsUndefined(it->isolate());
    1195          30 :         } else if (!info->getter()->IsUndefined(it->isolate()) ||
    1196             :                    !info->query()->IsUndefined(it->isolate())) {
    1197             :           return false;
    1198             :         }
    1199             :         break;
    1200             :       }
    1201             :       case LookupIterator::ACCESS_CHECK:
    1202        2730 :         if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
    1203             :         break;
    1204             :       case LookupIterator::ACCESSOR:
    1205      254176 :         return !it->IsReadOnly();
    1206             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    1207          81 :         return false;
    1208             :       case LookupIterator::DATA: {
    1209      347350 :         if (it->IsReadOnly()) return false;
    1210             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
    1211      331925 :         if (receiver.is_identical_to(holder)) {
    1212      223939 :           it->PrepareForDataProperty(value);
    1213             :           // The previous receiver map might just have been deprecated,
    1214             :           // so reload it.
    1215      223939 :           update_receiver_map(receiver);
    1216      223939 :           return true;
    1217             :         }
    1218             : 
    1219             :         // Receiver != holder.
    1220      107986 :         if (receiver->IsJSGlobalProxy()) {
    1221         595 :           PrototypeIterator iter(it->isolate(), receiver);
    1222             :           return it->GetHolder<Object>().is_identical_to(
    1223             :               PrototypeIterator::GetCurrent(iter));
    1224             :         }
    1225             : 
    1226      107391 :         if (it->HolderIsReceiverOrHiddenPrototype()) return false;
    1227             : 
    1228      107391 :         if (it->ExtendingNonExtensible(receiver)) return false;
    1229             :         created_new_transition_ = it->PrepareTransitionToDataProperty(
    1230      107391 :             receiver, value, NONE, store_mode);
    1231      107391 :         return it->IsCacheableTransition();
    1232             :       }
    1233             :     }
    1234             :   }
    1235             : 
    1236      493219 :   receiver = it->GetStoreTarget();
    1237      493219 :   if (it->ExtendingNonExtensible(receiver)) return false;
    1238             :   created_new_transition_ =
    1239      493142 :       it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
    1240      493142 :   return it->IsCacheableTransition();
    1241             : }
    1242             : 
    1243     1508137 : MaybeHandle<Object> StoreGlobalIC::Store(Handle<Object> object,
    1244             :                                          Handle<Name> name,
    1245             :                                          Handle<Object> value) {
    1246             :   DCHECK(object->IsJSGlobalObject());
    1247             :   DCHECK(name->IsString());
    1248             : 
    1249             :   // Look up in script context table.
    1250     1508137 :   Handle<String> str_name = Handle<String>::cast(name);
    1251             :   Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
    1252             :   Handle<ScriptContextTable> script_contexts(
    1253             :       global->native_context()->script_context_table());
    1254             : 
    1255             :   ScriptContextTable::LookupResult lookup_result;
    1256     1508137 :   if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
    1257             :     Handle<Context> script_context = ScriptContextTable::GetContext(
    1258          73 :         script_contexts, lookup_result.context_index);
    1259          73 :     if (lookup_result.mode == CONST) {
    1260         111 :       return TypeError(MessageTemplate::kConstAssign, object, name);
    1261             :     }
    1262             : 
    1263             :     Handle<Object> previous_value =
    1264         106 :         FixedArray::get(*script_context, lookup_result.slot_index, isolate());
    1265             : 
    1266          53 :     if (previous_value->IsTheHole(isolate())) {
    1267             :       // Do not install stubs and stay pre-monomorphic for
    1268             :       // uninitialized accesses.
    1269          15 :       return ReferenceError(name);
    1270             :     }
    1271             : 
    1272          76 :     if (FLAG_use_ic && StoreScriptContextFieldStub::Accepted(&lookup_result)) {
    1273          38 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
    1274             :       StoreScriptContextFieldStub stub(isolate(), &lookup_result);
    1275          76 :       PatchCache(name, stub.GetCode());
    1276             :     }
    1277             : 
    1278          76 :     script_context->set(lookup_result.slot_index, *value);
    1279          38 :     return value;
    1280             :   }
    1281             : 
    1282     1508064 :   return StoreIC::Store(object, name, value);
    1283             : }
    1284             : 
    1285     4305028 : MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
    1286             :                                    Handle<Object> value,
    1287             :                                    JSReceiver::StoreFromKeyed store_mode) {
    1288             :   // TODO(verwaest): Let SetProperty do the migration, since storing a property
    1289             :   // might deprecate the current map again, if value does not fit.
    1290     4305028 :   if (MigrateDeprecated(object)) {
    1291             :     Handle<Object> result;
    1292         894 :     ASSIGN_RETURN_ON_EXCEPTION(
    1293             :         isolate(), result,
    1294             :         Object::SetProperty(object, name, value, language_mode()), Object);
    1295         447 :     return result;
    1296             :   }
    1297             : 
    1298             :   // If the object is undefined or null it's illegal to try to set any
    1299             :   // properties on it; throw a TypeError in that case.
    1300    22623507 :   if (object->IsNullOrUndefined(isolate())) {
    1301          68 :     if (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
    1302             :       // Ensure the IC state progresses.
    1303          10 :       TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
    1304          10 :       update_receiver_map(object);
    1305          20 :       PatchCache(name, slow_stub());
    1306          10 :       TRACE_IC("StoreIC", name);
    1307             :     }
    1308          34 :     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
    1309             :   }
    1310             : 
    1311     4304547 :   if (state() != UNINITIALIZED) {
    1312     1098273 :     JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
    1313             :   }
    1314             :   MaybeHandle<Object> cached_handler;
    1315             :   Handle<Map> transition_map;
    1316     4304545 :   if (object->IsJSReceiver()) {
    1317     4303862 :     name = isolate()->factory()->InternalizeName(name);
    1318             :     TransitionsAccessor transitions(receiver_map());
    1319     4303862 :     Object* maybe_handler = transitions.SearchHandler(*name, &transition_map);
    1320     4303862 :     if (maybe_handler != nullptr) {
    1321        3084 :       cached_handler = MaybeHandle<Object>(maybe_handler, isolate());
    1322             :     }
    1323             :   }
    1324             : 
    1325             :   LookupIterator it = LookupIterator::ForTransitionHandler(
    1326     4304545 :       isolate(), object, name, value, cached_handler, transition_map);
    1327     4304547 :   if (FLAG_use_ic) UpdateCaches(&it, value, store_mode, cached_handler);
    1328             : 
    1329     4304547 :   MAYBE_RETURN_NULL(
    1330             :       Object::SetProperty(&it, value, language_mode(), store_mode));
    1331     4287026 :   return value;
    1332             : }
    1333             : 
    1334     4304143 : void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
    1335             :                            JSReceiver::StoreFromKeyed store_mode,
    1336             :                            MaybeHandle<Object> cached_handler) {
    1337     4304143 :   if (state() == UNINITIALIZED) {
    1338             :     // This is the first time we execute this inline cache. Set the target to
    1339             :     // the pre monomorphic stub to delay setting the monomorphic state.
    1340     3205870 :     TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic);
    1341     3205870 :     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
    1342     3205870 :     TRACE_IC("StoreIC", lookup->name());
    1343     6674000 :     return;
    1344             :   }
    1345             : 
    1346             :   Handle<Object> handler;
    1347     1098273 :   if (!cached_handler.is_null()) {
    1348        2529 :     handler = cached_handler.ToHandleChecked();
    1349     1095744 :   } else if (LookupForWrite(lookup, value, store_mode)) {
    1350      966714 :     if (created_new_transition_) {
    1351             :       // The first time a transition is performed, there's a good chance that
    1352             :       // it won't be taken again, so don't bother creating a handler.
    1353      262260 :       TRACE_IC("StoreIC", lookup->name());
    1354      262260 :       return;
    1355             :     }
    1356      704454 :     handler = ComputeHandler(lookup);
    1357             :   } else {
    1358             :     TRACE_GENERIC_IC("LookupForWrite said 'false'");
    1359      129030 :     handler = slow_stub();
    1360             :   }
    1361             : 
    1362      836013 :   PatchCache(lookup->name(), handler);
    1363      836013 :   TRACE_IC("StoreIC", lookup->name());
    1364             : }
    1365             : 
    1366      704454 : Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
    1367      704454 :   switch (lookup->state()) {
    1368             :     case LookupIterator::TRANSITION: {
    1369             :       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1370             : 
    1371      225612 :       Handle<JSObject> store_target = lookup->GetStoreTarget();
    1372      225612 :       if (store_target->IsJSGlobalObject()) {
    1373      704377 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);
    1374             : 
    1375             :         Handle<Object> handler = StoreHandler::StoreTransition(
    1376             :             isolate(), receiver_map(), store_target, lookup->transition_cell(),
    1377        1790 :             lookup->name());
    1378        1790 :         return handler;
    1379             :       }
    1380             :       // Currently not handled by CompileStoreTransition.
    1381      223822 :       if (!holder->HasFastProperties()) {
    1382             :         TRACE_GENERIC_IC("transition from slow");
    1383        1439 :         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1384        1439 :         return slow_stub();
    1385             :       }
    1386             : 
    1387             :       DCHECK(lookup->IsCacheableTransition());
    1388             :       Handle<Map> transition = lookup->transition_map();
    1389      222383 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
    1390             :       Handle<Object> handler = StoreHandler::StoreTransition(
    1391      222383 :           isolate(), receiver_map(), holder, transition, lookup->name());
    1392             :       TransitionsAccessor(receiver_map())
    1393      222383 :           .UpdateHandler(*lookup->name(), *handler);
    1394      222383 :       return handler;
    1395             :     }
    1396             : 
    1397             :     case LookupIterator::INTERCEPTOR: {
    1398             :       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1399             :       USE(holder);
    1400             : 
    1401             :       DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
    1402         131 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
    1403             :       StoreInterceptorStub stub(isolate());
    1404         131 :       return stub.GetCode();
    1405             :     }
    1406             : 
    1407             :     case LookupIterator::ACCESSOR: {
    1408             :       // This is currently guaranteed by checks in StoreIC::Store.
    1409             :       Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
    1410             :       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1411             :       DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
    1412             : 
    1413      253843 :       if (!holder->HasFastProperties()) {
    1414             :         TRACE_GENERIC_IC("accessor on slow map");
    1415         295 :         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1416         295 :         return slow_stub();
    1417             :       }
    1418      253548 :       Handle<Object> accessors = lookup->GetAccessors();
    1419      253548 :       if (accessors->IsAccessorInfo()) {
    1420             :         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    1421      100704 :         if (v8::ToCData<Address>(info->setter()) == nullptr) {
    1422             :           TRACE_GENERIC_IC("setter == nullptr");
    1423           6 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1424           6 :           return slow_stub();
    1425             :         }
    1426      201289 :         if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
    1427      100591 :             !lookup->HolderIsReceiverOrHiddenPrototype()) {
    1428             :           TRACE_GENERIC_IC("special data property in prototype chain");
    1429          90 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1430          90 :           return slow_stub();
    1431             :         }
    1432      100608 :         if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
    1433      100608 :                                                    receiver_map())) {
    1434             :           TRACE_GENERIC_IC("incompatible receiver type");
    1435          12 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1436          12 :           return slow_stub();
    1437             :         }
    1438             :         break;  // Custom-compiled handler.
    1439      152844 :       } else if (accessors->IsAccessorPair()) {
    1440             :         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
    1441             :                               isolate());
    1442      164279 :         if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
    1443             :           TRACE_GENERIC_IC("setter not a function");
    1444       11205 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1445       11205 :           return slow_stub();
    1446             :         }
    1447      141639 :         CallOptimization call_optimization(setter);
    1448      141639 :         if (call_optimization.is_simple_api_call()) {
    1449         322 :           if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
    1450             :             break;  // Custom-compiled handler.
    1451             :           }
    1452             :           TRACE_GENERIC_IC("incompatible receiver");
    1453          48 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1454          48 :           return slow_stub();
    1455             :         }
    1456             :         break;  // Custom-compiled handler.
    1457             :       }
    1458           0 :       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1459           0 :       return slow_stub();
    1460             :     }
    1461             : 
    1462             :     case LookupIterator::DATA: {
    1463             :       // This is currently guaranteed by checks in StoreIC::Store.
    1464             :       Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
    1465             :       USE(receiver);
    1466             :       Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1467             :       DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
    1468             : 
    1469             :       DCHECK_EQ(kData, lookup->property_details().kind());
    1470      224514 :       if (lookup->is_dictionary_holder()) {
    1471       58269 :         if (holder->IsJSGlobalObject()) {
    1472       53153 :           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
    1473             :           return StoreHandler::StoreGlobal(isolate(),
    1474      106306 :                                            lookup->GetPropertyCell());
    1475             :         }
    1476        5116 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
    1477             :         DCHECK(holder.is_identical_to(receiver));
    1478        5116 :         return StoreHandler::StoreNormal(isolate());
    1479             :       }
    1480             : 
    1481             :       // -------------- Fields --------------
    1482      166245 :       if (lookup->property_details().location() == kField) {
    1483      166208 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
    1484      166208 :         int descriptor = lookup->GetFieldDescriptorIndex();
    1485      166208 :         FieldIndex index = lookup->GetFieldIndex();
    1486             :         PropertyConstness constness = lookup->constness();
    1487      166208 :         if (constness == kConst && IsStoreOwnICKind(nexus()->kind())) {
    1488             :           // StoreOwnICs are used for initializing object literals therefore
    1489             :           // we must store the value unconditionally even to kConst fields.
    1490             :           constness = kMutable;
    1491             :         }
    1492             :         return StoreHandler::StoreField(isolate(), descriptor, index, constness,
    1493      166208 :                                         lookup->representation());
    1494             :       }
    1495             : 
    1496             :       // -------------- Constant properties --------------
    1497             :       DCHECK_EQ(kDescriptor, lookup->property_details().location());
    1498             :       TRACE_GENERIC_IC("constant property");
    1499          37 :       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1500          37 :       return slow_stub();
    1501             :     }
    1502             :     case LookupIterator::JSPROXY: {
    1503             :       Handle<JSReceiver> receiver =
    1504         354 :           Handle<JSReceiver>::cast(lookup->GetReceiver());
    1505         354 :       Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
    1506             :       return StoreHandler::StoreProxy(isolate(), receiver_map(), holder,
    1507         354 :                                       receiver, lookup->name());
    1508             :     }
    1509             : 
    1510             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
    1511             :     case LookupIterator::ACCESS_CHECK:
    1512             :     case LookupIterator::NOT_FOUND:
    1513           0 :       UNREACHABLE();
    1514             :   }
    1515      242187 :   return Handle<Code>::null();
    1516             : }
    1517             : 
    1518      242187 : Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup) {
    1519             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
    1520             : 
    1521             :   // This is currently guaranteed by checks in StoreIC::Store.
    1522      242187 :   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
    1523             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1524             :   DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
    1525             : 
    1526             :   DCHECK(holder->HasFastProperties());
    1527      242187 :   Handle<Object> accessors = lookup->GetAccessors();
    1528             : 
    1529      242187 :   if (accessors->IsAccessorInfo()) {
    1530      100596 :     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    1531             :     DCHECK_NOT_NULL(v8::ToCData<Address>(info->setter()));
    1532             :     DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
    1533             :            lookup->HolderIsReceiverOrHiddenPrototype());
    1534             :     DCHECK(
    1535             :         AccessorInfo::IsCompatibleReceiverMap(isolate(), info, receiver_map()));
    1536      383778 :     TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
    1537             :     NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
    1538             :     // TODO(ishell): don't hard-code language mode into the handler because
    1539             :     // this handler can be re-used through megamorphic stub cache for wrong
    1540             :     // language mode.
    1541             :     // Better pass vector/slot to Runtime::kStoreCallbackProperty and
    1542             :     // let it decode the language mode from the IC kind.
    1543             :     Handle<Code> code = compiler.CompileStoreCallback(receiver, lookup->name(),
    1544      100596 :                                                       info, language_mode());
    1545      100596 :     return code;
    1546             :   }
    1547             : 
    1548             :   DCHECK(accessors->IsAccessorPair());
    1549             :   Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
    1550             :                         isolate());
    1551             :   DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
    1552      141591 :   CallOptimization call_optimization(setter);
    1553             :   NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
    1554      141591 :   if (call_optimization.is_simple_api_call()) {
    1555             :     DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
    1556         274 :     TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
    1557             :     Handle<Code> code = compiler.CompileStoreCallback(
    1558             :         receiver, lookup->name(), call_optimization, lookup->GetAccessorIndex(),
    1559         274 :         slow_stub());
    1560         274 :     return code;
    1561             :   }
    1562      141317 :   TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
    1563             :   int expected_arguments =
    1564             :       JSFunction::cast(*setter)->shared()->internal_formal_parameter_count();
    1565             :   return compiler.CompileStoreViaSetter(
    1566      141317 :       receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
    1567             : }
    1568             : 
    1569      150722 : void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
    1570             :                                       KeyedAccessStoreMode store_mode) {
    1571             :   MapHandles target_receiver_maps;
    1572      164305 :   TargetMaps(&target_receiver_maps);
    1573      150722 :   if (target_receiver_maps.empty()) {
    1574             :     Handle<Map> monomorphic_map =
    1575      137119 :         ComputeTransitionedMap(receiver_map, store_mode);
    1576             :     store_mode = GetNonTransitioningStoreMode(store_mode);
    1577      137119 :     Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
    1578      137119 :     return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
    1579             :   }
    1580             : 
    1581       51857 :   for (Handle<Map> map : target_receiver_maps) {
    1582       38274 :     if (!map.is_null() && map->instance_type() == JS_VALUE_TYPE) {
    1583             :       TRACE_GENERIC_IC("JSValue");
    1584             :       return;
    1585             :     }
    1586             :   }
    1587             : 
    1588             :   // There are several special cases where an IC that is MONOMORPHIC can still
    1589             :   // transition to a different GetNonTransitioningStoreMode IC that handles a
    1590             :   // superset of the original IC. Handle those here if the receiver map hasn't
    1591             :   // changed or it has transitioned to a more general kind.
    1592             :   KeyedAccessStoreMode old_store_mode;
    1593             :   old_store_mode = GetKeyedAccessStoreMode();
    1594       13583 :   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
    1595       13583 :   if (state() == MONOMORPHIC) {
    1596             :     Handle<Map> transitioned_receiver_map = receiver_map;
    1597       10517 :     if (IsTransitionStoreMode(store_mode)) {
    1598             :       transitioned_receiver_map =
    1599        2762 :           ComputeTransitionedMap(receiver_map, store_mode);
    1600             :     }
    1601       13351 :     if ((receiver_map.is_identical_to(previous_receiver_map) &&
    1602       19465 :          IsTransitionStoreMode(store_mode)) ||
    1603             :         IsTransitionOfMonomorphicTarget(*previous_receiver_map,
    1604        8948 :                                         *transitioned_receiver_map)) {
    1605             :       // If the "old" and "new" maps are in the same elements map family, or
    1606             :       // if they at least come from the same origin for a transitioning store,
    1607             :       // stay MONOMORPHIC and use the map for the most generic ElementsKind.
    1608             :       store_mode = GetNonTransitioningStoreMode(store_mode);
    1609             :       Handle<Object> handler =
    1610        4872 :           StoreElementHandler(transitioned_receiver_map, store_mode);
    1611        4872 :       ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
    1612             :       return;
    1613             :     }
    1614        6910 :     if (receiver_map.is_identical_to(previous_receiver_map) &&
    1615        6663 :         old_store_mode == STANDARD_STORE &&
    1616        2036 :         (store_mode == STORE_AND_GROW_NO_TRANSITION ||
    1617        1874 :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    1618             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
    1619             :       // A "normal" IC that handles stores can switch to a version that can
    1620             :       // grow at the end of the array, handle OOB accesses or copy COW arrays
    1621             :       // and still stay MONOMORPHIC.
    1622         187 :       Handle<Object> handler = StoreElementHandler(receiver_map, store_mode);
    1623         187 :       return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
    1624             :     }
    1625             :   }
    1626             : 
    1627             :   DCHECK(state() != GENERIC);
    1628             : 
    1629             :   bool map_added =
    1630        8524 :       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
    1631             : 
    1632        8524 :   if (IsTransitionStoreMode(store_mode)) {
    1633             :     Handle<Map> transitioned_receiver_map =
    1634        1321 :         ComputeTransitionedMap(receiver_map, store_mode);
    1635             :     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
    1636        1321 :                                             transitioned_receiver_map);
    1637             :   }
    1638             : 
    1639        8524 :   if (!map_added) {
    1640             :     // If the miss wasn't due to an unseen map, a polymorphic stub
    1641             :     // won't help, use the megamorphic stub which can handle everything.
    1642             :     TRACE_GENERIC_IC("same map added twice");
    1643             :     return;
    1644             :   }
    1645             : 
    1646             :   // If the maximum number of receiver maps has been exceeded, use the
    1647             :   // megamorphic version of the IC.
    1648       14370 :   if (target_receiver_maps.size() > kMaxKeyedPolymorphism) return;
    1649             : 
    1650             :   // Make sure all polymorphic handlers have the same store mode, otherwise the
    1651             :   // megamorphic stub must be used.
    1652             :   store_mode = GetNonTransitioningStoreMode(store_mode);
    1653        6381 :   if (old_store_mode != STANDARD_STORE) {
    1654         935 :     if (store_mode == STANDARD_STORE) {
    1655             :       store_mode = old_store_mode;
    1656         751 :     } else if (store_mode != old_store_mode) {
    1657             :       TRACE_GENERIC_IC("store mode mismatch");
    1658             :       return;
    1659             :     }
    1660             :   }
    1661             : 
    1662             :   // If the store mode isn't the standard mode, make sure that all polymorphic
    1663             :   // receivers are either external arrays, or all "normal" arrays. Otherwise,
    1664             :   // use the megamorphic stub.
    1665        6354 :   if (store_mode != STANDARD_STORE) {
    1666             :     size_t external_arrays = 0;
    1667        6246 :     for (Handle<Map> map : target_receiver_maps) {
    1668        2545 :       if (map->has_fixed_typed_array_elements()) {
    1669          30 :         external_arrays++;
    1670             :       }
    1671             :     }
    1672        1156 :     if (external_arrays != 0 &&
    1673             :         external_arrays != target_receiver_maps.size()) {
    1674             :       TRACE_GENERIC_IC("unsupported combination of external and normal arrays");
    1675             :       return;
    1676             :     }
    1677             :   }
    1678             : 
    1679             :   ObjectHandles handlers;
    1680        6324 :   handlers.reserve(target_receiver_maps.size());
    1681        6324 :   StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
    1682       12648 :   if (target_receiver_maps.size() == 0) {
    1683          10 :     ConfigureVectorState(PREMONOMORPHIC, Handle<Name>());
    1684        6314 :   } else if (target_receiver_maps.size() == 1) {
    1685          20 :     ConfigureVectorState(Handle<Name>(), target_receiver_maps[0], handlers[0]);
    1686             :   } else {
    1687        6304 :     ConfigureVectorState(Handle<Name>(), target_receiver_maps, &handlers);
    1688             :   }
    1689             : }
    1690             : 
    1691             : 
    1692      141202 : Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
    1693             :     Handle<Map> map, KeyedAccessStoreMode store_mode) {
    1694      141202 :   switch (store_mode) {
    1695             :     case STORE_TRANSITION_TO_OBJECT:
    1696             :     case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
    1697             :       ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
    1698             :                               ? HOLEY_ELEMENTS
    1699       18627 :                               : PACKED_ELEMENTS;
    1700       18627 :       return Map::TransitionElementsTo(map, kind);
    1701             :     }
    1702             :     case STORE_TRANSITION_TO_DOUBLE:
    1703             :     case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
    1704             :       ElementsKind kind = IsHoleyElementsKind(map->elements_kind())
    1705             :                               ? HOLEY_DOUBLE_ELEMENTS
    1706        3662 :                               : PACKED_DOUBLE_ELEMENTS;
    1707        3662 :       return Map::TransitionElementsTo(map, kind);
    1708             :     }
    1709             :     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
    1710             :       DCHECK(map->has_fixed_typed_array_elements());
    1711             :     // Fall through
    1712             :     case STORE_NO_TRANSITION_HANDLE_COW:
    1713             :     case STANDARD_STORE:
    1714             :     case STORE_AND_GROW_NO_TRANSITION:
    1715      118913 :       return map;
    1716             :   }
    1717           0 :   UNREACHABLE();
    1718             : }
    1719             : 
    1720      155809 : Handle<Object> KeyedStoreIC::StoreElementHandler(
    1721             :     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
    1722             :   DCHECK(store_mode == STANDARD_STORE ||
    1723             :          store_mode == STORE_AND_GROW_NO_TRANSITION ||
    1724             :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    1725             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
    1726             :   DCHECK(!receiver_map->DictionaryElementsInPrototypeChainOnly());
    1727             : 
    1728      155809 :   if (receiver_map->IsJSProxyMap()) {
    1729      463301 :     return StoreHandler::StoreProxy(isolate());
    1730             :   }
    1731             : 
    1732             :   ElementsKind elements_kind = receiver_map->elements_kind();
    1733      155746 :   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
    1734             :   Handle<Code> stub;
    1735      155746 :   if (receiver_map->has_sloppy_arguments_elements()) {
    1736           0 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
    1737           0 :     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
    1738      177742 :   } else if (receiver_map->has_fast_elements() ||
    1739             :              receiver_map->has_fixed_typed_array_elements()) {
    1740      153915 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
    1741             :     stub =
    1742             :         StoreFastElementStub(isolate(), is_jsarray, elements_kind, store_mode)
    1743      307830 :             .GetCode();
    1744             :   } else {
    1745        1831 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
    1746             :     DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
    1747        3662 :     stub = StoreSlowElementStub(isolate(), store_mode).GetCode();
    1748             :   }
    1749             :   Handle<Object> validity_cell =
    1750      155746 :       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
    1751      155746 :   if (validity_cell.is_null()) return stub;
    1752      151746 :   return isolate()->factory()->NewTuple2(validity_cell, stub, TENURED);
    1753             : }
    1754             : 
    1755        6324 : void KeyedStoreIC::StoreElementPolymorphicHandlers(
    1756             :     MapHandles* receiver_maps, ObjectHandles* handlers,
    1757             :     KeyedAccessStoreMode store_mode) {
    1758             :   DCHECK(store_mode == STANDARD_STORE ||
    1759             :          store_mode == STORE_AND_GROW_NO_TRANSITION ||
    1760             :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    1761             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
    1762             : 
    1763             :   // Filter out deprecated maps to ensure their instances get migrated.
    1764             :   receiver_maps->erase(
    1765             :       std::remove_if(
    1766             :           receiver_maps->begin(), receiver_maps->end(),
    1767             :           [](const Handle<Map>& map) { return map->is_deprecated(); }),
    1768        6324 :       receiver_maps->end());
    1769             : 
    1770       28220 :   for (Handle<Map> receiver_map : *receiver_maps) {
    1771             :     Handle<Object> handler;
    1772             :     Handle<Map> transition;
    1773             : 
    1774       31124 :     if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
    1775       15552 :         receiver_map->DictionaryElementsInPrototypeChainOnly()) {
    1776             :       // TODO(mvstanton): Consider embedding store_mode in the state of the slow
    1777             :       // keyed store ic for uniformity.
    1778        1941 :       TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
    1779          30 :       handler = BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
    1780             : 
    1781             :     } else {
    1782             :       {
    1783             :         Map* tmap =
    1784       15542 :             receiver_map->FindElementsKindTransitionedMap(*receiver_maps);
    1785       15542 :         if (tmap != nullptr) {
    1786        1911 :           if (receiver_map->is_stable()) {
    1787          40 :             receiver_map->NotifyLeafMapLayoutChange();
    1788             :           }
    1789             :           transition = handle(tmap);
    1790             :         }
    1791             :       }
    1792             : 
    1793             :       // TODO(mvstanton): The code below is doing pessimistic elements
    1794             :       // transitions. I would like to stop doing that and rely on Allocation
    1795             :       // Site Tracking to do a better job of ensuring the data types are what
    1796             :       // they need to be. Not all the elements are in place yet, pessimistic
    1797             :       // elements transitions are still important for performance.
    1798       15542 :       if (!transition.is_null()) {
    1799        1911 :         TRACE_HANDLER_STATS(isolate(),
    1800             :                             KeyedStoreIC_ElementsTransitionAndStoreStub);
    1801             :         handler = StoreHandler::StoreElementTransition(isolate(), receiver_map,
    1802        1911 :                                                        transition, store_mode);
    1803             :       } else {
    1804       13631 :         handler = StoreElementHandler(receiver_map, store_mode);
    1805             :       }
    1806             :     }
    1807             :     DCHECK(!handler.is_null());
    1808       15572 :     handlers->push_back(handler);
    1809             :   }
    1810        6324 : }
    1811             : 
    1812      263348 : bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
    1813      263348 :   uint32_t length = 0;
    1814      263348 :   if (receiver->IsJSArray()) {
    1815             :     JSArray::cast(*receiver)->length()->ToArrayLength(&length);
    1816             :   } else {
    1817       29155 :     length = static_cast<uint32_t>(receiver->elements()->length());
    1818             :   }
    1819      263348 :   return index >= length;
    1820             : }
    1821             : 
    1822             : 
    1823      263348 : static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
    1824             :                                          uint32_t index, Handle<Object> value) {
    1825      263348 :   bool oob_access = IsOutOfBoundsAccess(receiver, index);
    1826             :   // Don't consider this a growing store if the store would send the receiver to
    1827             :   // dictionary mode.
    1828      380364 :   bool allow_growth = receiver->IsJSArray() && oob_access &&
    1829      117016 :                       !receiver->WouldConvertToSlowElements(index);
    1830      263348 :   if (allow_growth) {
    1831             :     // Handle growing array in stub if necessary.
    1832      116221 :     if (receiver->HasSmiElements()) {
    1833        7368 :       if (value->IsHeapNumber()) {
    1834             :         return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
    1835             :       }
    1836        6954 :       if (value->IsHeapObject()) {
    1837             :         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
    1838             :       }
    1839      108853 :     } else if (receiver->HasDoubleElements()) {
    1840         484 :       if (!value->IsSmi() && !value->IsHeapNumber()) {
    1841             :         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
    1842             :       }
    1843             :     }
    1844             :     return STORE_AND_GROW_NO_TRANSITION;
    1845             :   } else {
    1846             :     // Handle only in-bounds elements accesses.
    1847      147127 :     if (receiver->HasSmiElements()) {
    1848       75188 :       if (value->IsHeapNumber()) {
    1849             :         return STORE_TRANSITION_TO_DOUBLE;
    1850       72331 :       } else if (value->IsHeapObject()) {
    1851             :         return STORE_TRANSITION_TO_OBJECT;
    1852             :       }
    1853       71939 :     } else if (receiver->HasDoubleElements()) {
    1854        8623 :       if (!value->IsSmi() && !value->IsHeapNumber()) {
    1855             :         return STORE_TRANSITION_TO_OBJECT;
    1856             :       }
    1857             :     }
    1858      373380 :     if (!FLAG_trace_external_array_abuse &&
    1859      141367 :         receiver->map()->has_fixed_typed_array_elements() && oob_access) {
    1860             :       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
    1861             :     }
    1862      123915 :     Heap* heap = receiver->GetHeap();
    1863      123915 :     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
    1864             :       return STORE_NO_TRANSITION_HANDLE_COW;
    1865             :     } else {
    1866      122911 :       return STANDARD_STORE;
    1867             :     }
    1868             :   }
    1869             : }
    1870             : 
    1871             : 
    1872      320862 : MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
    1873             :                                         Handle<Object> key,
    1874             :                                         Handle<Object> value) {
    1875             :   // TODO(verwaest): Let SetProperty do the migration, since storing a property
    1876             :   // might deprecate the current map again, if value does not fit.
    1877      320862 :   if (MigrateDeprecated(object)) {
    1878             :     Handle<Object> result;
    1879     1146095 :     ASSIGN_RETURN_ON_EXCEPTION(
    1880             :         isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
    1881             :                                                       value, language_mode()),
    1882             :         Object);
    1883          37 :     return result;
    1884             :   }
    1885             : 
    1886             :   // Check for non-string values that can be converted into an
    1887             :   // internalized string directly or is representable as a smi.
    1888      320825 :   key = TryConvertKey(key, isolate());
    1889             : 
    1890             :   Handle<Object> store_handle;
    1891             : 
    1892             :   uint32_t index;
    1893      345964 :   if ((key->IsInternalizedString() &&
    1894      642609 :        !String::cast(*key)->AsArrayIndex(&index)) ||
    1895             :       key->IsSymbol()) {
    1896      103612 :     ASSIGN_RETURN_ON_EXCEPTION(
    1897             :         isolate(), store_handle,
    1898             :         StoreIC::Store(object, Handle<Name>::cast(key), value,
    1899             :                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
    1900             :         Object);
    1901       50808 :     if (vector_needs_update()) {
    1902       21315 :       ConfigureVectorState(MEGAMORPHIC, key);
    1903             :       TRACE_GENERIC_IC("unhandled internalized string key");
    1904       21315 :       TRACE_IC("StoreIC", key);
    1905             :     }
    1906       50808 :     return store_handle;
    1907             :   }
    1908             : 
    1909      269019 :   if (state() != UNINITIALIZED) {
    1910       20030 :     JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
    1911             :   }
    1912             : 
    1913      537779 :   bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
    1914      537743 :                 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
    1915      537603 :   if (use_ic && !object->IsSmi()) {
    1916             :     // Don't use ICs for maps of the objects in Array's prototype chain. We
    1917             :     // expect to be able to trap element sets to objects with those maps in
    1918             :     // the runtime to enable optimization of element hole access.
    1919             :     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
    1920      268142 :     if (heap_object->map()->IsMapInArrayPrototypeChain()) {
    1921             :       TRACE_GENERIC_IC("map in array prototype");
    1922             :       use_ic = false;
    1923             :     }
    1924             :   }
    1925             : 
    1926             :   Handle<Map> old_receiver_map;
    1927             :   bool is_arguments = false;
    1928             :   bool key_is_valid_index = false;
    1929             :   KeyedAccessStoreMode store_mode = STANDARD_STORE;
    1930      536816 :   if (use_ic && object->IsJSReceiver()) {
    1931             :     Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    1932             :     old_receiver_map = handle(receiver->map(), isolate());
    1933             :     is_arguments = receiver->IsJSArgumentsObject();
    1934             :     bool is_proxy = receiver->IsJSProxy();
    1935      532618 :     key_is_valid_index = key->IsSmi() && Smi::ToInt(*key) >= 0;
    1936      267128 :     if (!is_arguments && !is_proxy) {
    1937      265373 :       if (key_is_valid_index) {
    1938      263348 :         uint32_t index = static_cast<uint32_t>(Smi::ToInt(*key));
    1939      263348 :         Handle<JSObject> receiver_object = Handle<JSObject>::cast(object);
    1940      263348 :         store_mode = GetStoreMode(receiver_object, index, value);
    1941             :       }
    1942             :     }
    1943             :   }
    1944             : 
    1945             :   DCHECK(store_handle.is_null());
    1946      807057 :   ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
    1947             :                              Runtime::SetObjectProperty(isolate(), object, key,
    1948             :                                                         value, language_mode()),
    1949             :                              Object);
    1950             : 
    1951      163274 :   if (use_ic) {
    1952      162083 :     if (!old_receiver_map.is_null()) {
    1953      161501 :       if (is_arguments) {
    1954             :         TRACE_GENERIC_IC("arguments receiver");
    1955      160259 :       } else if (key_is_valid_index) {
    1956      158847 :         if (old_receiver_map->is_abandoned_prototype_map()) {
    1957             :           TRACE_GENERIC_IC("receiver with prototype map");
    1958      158769 :         } else if (!old_receiver_map
    1959      158769 :                         ->DictionaryElementsInPrototypeChainOnly()) {
    1960             :           // We should go generic if receiver isn't a dictionary, but our
    1961             :           // prototype chain does have dictionary elements. This ensures that
    1962             :           // other non-dictionary receivers in the polymorphic case benefit
    1963             :           // from fast path keyed stores.
    1964      150722 :           UpdateStoreElement(old_receiver_map, store_mode);
    1965             :         } else {
    1966             :           TRACE_GENERIC_IC("dictionary or proxy prototype");
    1967             :         }
    1968             :       } else {
    1969             :         TRACE_GENERIC_IC("non-smi-like key");
    1970             :       }
    1971             :     } else {
    1972             :       TRACE_GENERIC_IC("non-JSObject receiver");
    1973             :     }
    1974             :   }
    1975             : 
    1976      163274 :   if (vector_needs_update()) {
    1977       14772 :     ConfigureVectorState(MEGAMORPHIC, key);
    1978             :   }
    1979      163274 :   TRACE_IC("StoreIC", key);
    1980             : 
    1981      163274 :   return store_handle;
    1982             : }
    1983             : 
    1984             : 
    1985             : #undef TRACE_IC
    1986             : 
    1987             : 
    1988             : // ----------------------------------------------------------------------------
    1989             : // Static IC stub generators.
    1990             : //
    1991             : 
    1992             : // Used from ic-<arch>.cc.
    1993     3721165 : RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
    1994     1860583 :   HandleScope scope(isolate);
    1995             :   DCHECK_EQ(4, args.length());
    1996             :   // Runtime functions don't follow the IC's calling convention.
    1997     1860583 :   Handle<Object> receiver = args.at(0);
    1998     1860583 :   Handle<Name> key = args.at<Name>(1);
    1999     1860583 :   Handle<Smi> slot = args.at<Smi>(2);
    2000     1860583 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
    2001     1860583 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2002             :   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
    2003             :   // LoadIC miss handler if the handler misses. Since the vector Nexus is
    2004             :   // set up outside the IC, handle that here.
    2005     1860583 :   FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2006     1860583 :   if (IsLoadICKind(kind)) {
    2007     1860455 :     LoadICNexus nexus(vector, vector_slot);
    2008     3720909 :     LoadIC ic(isolate, &nexus);
    2009     1860455 :     ic.UpdateState(receiver, key);
    2010     5581362 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2011             : 
    2012         128 :   } else if (IsLoadGlobalICKind(kind)) {
    2013             :     DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
    2014         118 :     receiver = isolate->global_object();
    2015         118 :     LoadGlobalICNexus nexus(vector, vector_slot);
    2016         236 :     LoadGlobalIC ic(isolate, &nexus);
    2017         118 :     ic.UpdateState(receiver, key);
    2018         354 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
    2019             : 
    2020             :   } else {
    2021             :     DCHECK(IsKeyedLoadICKind(kind));
    2022          10 :     KeyedLoadICNexus nexus(vector, vector_slot);
    2023          20 :     KeyedLoadIC ic(isolate, &nexus);
    2024          10 :     ic.UpdateState(receiver, key);
    2025          30 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2026     1860582 :   }
    2027             : }
    2028             : 
    2029             : // Used from ic-<arch>.cc.
    2030     3765504 : RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
    2031     1882752 :   HandleScope scope(isolate);
    2032             :   DCHECK_EQ(3, args.length());
    2033             :   // Runtime functions don't follow the IC's calling convention.
    2034     1882752 :   Handle<JSGlobalObject> global = isolate->global_object();
    2035     1882752 :   Handle<String> name = args.at<String>(0);
    2036     1882752 :   Handle<Smi> slot = args.at<Smi>(1);
    2037     1882752 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2038     1882752 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2039             : 
    2040     3765504 :   LoadGlobalICNexus nexus(vector, vector_slot);
    2041     3765503 :   LoadGlobalIC ic(isolate, &nexus);
    2042     1882753 :   ic.UpdateState(global, name);
    2043             : 
    2044             :   Handle<Object> result;
    2045     3765504 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
    2046     1882752 :   return *result;
    2047             : }
    2048             : 
    2049        1568 : RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
    2050         784 :   HandleScope scope(isolate);
    2051             :   DCHECK_EQ(3, args.length());
    2052        1568 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
    2053             : 
    2054         784 :   Handle<Context> native_context = isolate->native_context();
    2055             :   Handle<ScriptContextTable> script_contexts(
    2056         784 :       native_context->script_context_table());
    2057             : 
    2058             :   ScriptContextTable::LookupResult lookup_result;
    2059         784 :   if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
    2060             :     Handle<Context> script_context = ScriptContextTable::GetContext(
    2061           0 :         script_contexts, lookup_result.context_index);
    2062             :     Handle<Object> result =
    2063           0 :         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
    2064           0 :     if (*result == isolate->heap()->the_hole_value()) {
    2065           0 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2066             :           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
    2067             :     }
    2068             :     return *result;
    2069             :   }
    2070             : 
    2071         784 :   Handle<JSGlobalObject> global(native_context->global_object(), isolate);
    2072             :   Handle<Object> result;
    2073         784 :   bool is_found = false;
    2074        1568 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    2075             :       isolate, result,
    2076             :       Runtime::GetObjectProperty(isolate, global, name, &is_found));
    2077         784 :   if (!is_found) {
    2078           0 :     Handle<Smi> slot = args.at<Smi>(1);
    2079           0 :     Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2080           0 :     FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2081           0 :     FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2082             :     // It is actually a LoadGlobalICs here but the predicate handles this case
    2083             :     // properly.
    2084           0 :     if (LoadIC::ShouldThrowReferenceError(kind)) {
    2085           0 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2086             :           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
    2087             :     }
    2088             :   }
    2089         784 :   return *result;
    2090             : }
    2091             : 
    2092             : // Used from ic-<arch>.cc
    2093      561682 : RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
    2094      280841 :   HandleScope scope(isolate);
    2095             :   DCHECK_EQ(4, args.length());
    2096             :   // Runtime functions don't follow the IC's calling convention.
    2097      280841 :   Handle<Object> receiver = args.at(0);
    2098      280841 :   Handle<Object> key = args.at(1);
    2099      280841 :   Handle<Smi> slot = args.at<Smi>(2);
    2100      280841 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
    2101      280841 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2102      561682 :   KeyedLoadICNexus nexus(vector, vector_slot);
    2103      561682 :   KeyedLoadIC ic(isolate, &nexus);
    2104      280841 :   ic.UpdateState(receiver, key);
    2105      842523 :   RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2106             : }
    2107             : 
    2108             : // Used from ic-<arch>.cc.
    2109     8506590 : RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
    2110     4253295 :   HandleScope scope(isolate);
    2111             :   DCHECK_EQ(5, args.length());
    2112             :   // Runtime functions don't follow the IC's calling convention.
    2113     4253295 :   Handle<Object> value = args.at(0);
    2114     4253295 :   Handle<Smi> slot = args.at<Smi>(1);
    2115     4253295 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2116     4253295 :   Handle<Object> receiver = args.at(3);
    2117     4253295 :   Handle<Name> key = args.at<Name>(4);
    2118     4253295 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2119     4253295 :   FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2120     4253295 :   if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) {
    2121     2745158 :     StoreICNexus nexus(vector, vector_slot);
    2122     5490315 :     StoreIC ic(isolate, &nexus);
    2123     2745158 :     ic.UpdateState(receiver, key);
    2124     8235473 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2125     1508137 :   } else if (IsStoreGlobalICKind(kind)) {
    2126     1508137 :     StoreICNexus nexus(vector, vector_slot);
    2127     3016274 :     StoreGlobalIC ic(isolate, &nexus);
    2128     1508137 :     ic.UpdateState(receiver, key);
    2129     4524411 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2130             :   } else {
    2131             :     DCHECK(IsKeyedStoreICKind(kind));
    2132           0 :     KeyedStoreICNexus nexus(vector, vector_slot);
    2133           0 :     KeyedStoreIC ic(isolate, &nexus);
    2134           0 :     ic.UpdateState(receiver, key);
    2135           0 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2136     4253295 :   }
    2137             : }
    2138             : 
    2139       20530 : RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
    2140       10265 :   HandleScope scope(isolate);
    2141             :   DCHECK_EQ(5, args.length());
    2142             :   // Runtime functions don't follow the IC's calling convention.
    2143       10265 :   Handle<Object> value = args.at(0);
    2144       10265 :   Handle<Smi> slot = args.at<Smi>(1);
    2145       10265 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2146       10265 :   Handle<Object> object = args.at(3);
    2147       20530 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 4);
    2148             : 
    2149       10265 :   Handle<Context> native_context = isolate->native_context();
    2150             :   Handle<ScriptContextTable> script_contexts(
    2151       10265 :       native_context->script_context_table());
    2152             : 
    2153             :   ScriptContextTable::LookupResult lookup_result;
    2154       10265 :   if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
    2155             :     Handle<Context> script_context = ScriptContextTable::GetContext(
    2156          20 :         script_contexts, lookup_result.context_index);
    2157          20 :     if (lookup_result.mode == CONST) {
    2158          20 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2159             :           isolate, NewTypeError(MessageTemplate::kConstAssign, object, name));
    2160             :     }
    2161             : 
    2162             :     Handle<Object> previous_value =
    2163          20 :         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
    2164             : 
    2165          10 :     if (previous_value->IsTheHole(isolate)) {
    2166           0 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2167             :           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
    2168             :     }
    2169             : 
    2170          20 :     script_context->set(lookup_result.slot_index, *value);
    2171             :     return *value;
    2172             :   }
    2173             : 
    2174       10245 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2175       10245 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2176       20490 :   RETURN_RESULT_OR_FAILURE(
    2177             :       isolate,
    2178       10265 :       Runtime::SetObjectProperty(isolate, object, name, value, language_mode));
    2179             : }
    2180             : 
    2181             : // Used from ic-<arch>.cc.
    2182      641724 : RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
    2183      320862 :   HandleScope scope(isolate);
    2184             :   DCHECK_EQ(5, args.length());
    2185             :   // Runtime functions don't follow the IC's calling convention.
    2186      320862 :   Handle<Object> value = args.at(0);
    2187      320862 :   Handle<Smi> slot = args.at<Smi>(1);
    2188      320862 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2189      320862 :   Handle<Object> receiver = args.at(3);
    2190      320862 :   Handle<Object> key = args.at(4);
    2191      320862 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2192      641724 :   KeyedStoreICNexus nexus(vector, vector_slot);
    2193      641724 :   KeyedStoreIC ic(isolate, &nexus);
    2194      320862 :   ic.UpdateState(receiver, key);
    2195      962586 :   RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2196             : }
    2197             : 
    2198             : 
    2199     1507612 : RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
    2200      753806 :   HandleScope scope(isolate);
    2201             :   DCHECK_EQ(5, args.length());
    2202             :   // Runtime functions don't follow the IC's calling convention.
    2203      753806 :   Handle<Object> value = args.at(0);
    2204      753806 :   Handle<Smi> slot = args.at<Smi>(1);
    2205      753806 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2206      753806 :   Handle<Object> object = args.at(3);
    2207      753806 :   Handle<Object> key = args.at(4);
    2208      753806 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2209      753806 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2210     1507612 :   RETURN_RESULT_OR_FAILURE(
    2211             :       isolate,
    2212      753806 :       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
    2213             : }
    2214             : 
    2215             : 
    2216        1412 : RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
    2217         706 :   HandleScope scope(isolate);
    2218             :   DCHECK_EQ(6, args.length());
    2219             :   // Runtime functions don't follow the IC's calling convention.
    2220         706 :   Handle<Object> object = args.at(0);
    2221         706 :   Handle<Object> key = args.at(1);
    2222         706 :   Handle<Object> value = args.at(2);
    2223         706 :   Handle<Map> map = args.at<Map>(3);
    2224         706 :   Handle<Smi> slot = args.at<Smi>(4);
    2225         706 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(5);
    2226         706 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2227         706 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2228         706 :   if (object->IsJSObject()) {
    2229             :     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
    2230         706 :                                      map->elements_kind());
    2231             :   }
    2232        1412 :   RETURN_RESULT_OR_FAILURE(
    2233             :       isolate,
    2234         706 :       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
    2235             : }
    2236             : 
    2237             : 
    2238           0 : RUNTIME_FUNCTION(Runtime_Unreachable) {
    2239           0 :   UNREACHABLE();
    2240             :   CHECK(false);
    2241             :   return isolate->heap()->undefined_value();
    2242             : }
    2243             : 
    2244             : 
    2245     1268954 : RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
    2246      634477 :   Handle<JSObject> receiver = args.at<JSObject>(0);
    2247      634477 :   Handle<JSObject> holder = args.at<JSObject>(1);
    2248      634477 :   Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
    2249      634477 :   Handle<Name> name = args.at<Name>(3);
    2250      634477 :   Handle<Object> value = args.at(4);
    2251     1268954 :   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
    2252      634477 :   HandleScope scope(isolate);
    2253             : 
    2254      634477 :   if (V8_UNLIKELY(FLAG_runtime_stats)) {
    2255           0 :     RETURN_RESULT_OR_FAILURE(
    2256             :         isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
    2257             :                                             language_mode));
    2258             :   }
    2259             : 
    2260             :   Handle<AccessorInfo> callback(
    2261             :       callback_or_cell->IsWeakCell()
    2262         601 :           ? AccessorInfo::cast(WeakCell::cast(*callback_or_cell)->value())
    2263      634477 :           : AccessorInfo::cast(*callback_or_cell));
    2264             : 
    2265             :   DCHECK(callback->IsCompatibleReceiver(*receiver));
    2266             : 
    2267      634477 :   Address setter_address = v8::ToCData<Address>(callback->setter());
    2268             :   v8::AccessorNameSetterCallback fun =
    2269      634477 :       FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
    2270             :   DCHECK_NOT_NULL(fun);
    2271             : 
    2272             :   Object::ShouldThrow should_throw =
    2273      634477 :       is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
    2274             :   PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
    2275     1268954 :                                         *holder, should_throw);
    2276      634477 :   custom_args.Call(fun, name, value);
    2277      634477 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2278      634477 :   return *value;
    2279             : }
    2280             : 
    2281             : 
    2282             : /**
    2283             :  * Loads a property with an interceptor performing post interceptor
    2284             :  * lookup if interceptor failed.
    2285             :  */
    2286      559032 : RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
    2287      279516 :   HandleScope scope(isolate);
    2288             :   DCHECK_EQ(5, args.length());
    2289      279516 :   Handle<Name> name = args.at<Name>(0);
    2290      279516 :   Handle<Object> receiver = args.at(1);
    2291      279516 :   Handle<JSObject> holder = args.at<JSObject>(2);
    2292             : 
    2293      279516 :   if (!receiver->IsJSReceiver()) {
    2294          10 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    2295             :         isolate, receiver, Object::ConvertReceiver(isolate, receiver));
    2296             :   }
    2297             : 
    2298      279516 :   InterceptorInfo* interceptor = holder->GetNamedInterceptor();
    2299             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2300      559032 :                                       *holder, Object::DONT_THROW);
    2301             : 
    2302             :   v8::GenericNamedPropertyGetterCallback getter =
    2303             :       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
    2304      279516 :           interceptor->getter());
    2305      279516 :   Handle<Object> result = arguments.Call(getter, name);
    2306             : 
    2307      279516 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2308             : 
    2309      279504 :   if (!result.is_null()) return *result;
    2310             : 
    2311      200610 :   LookupIterator it(receiver, name, holder);
    2312             :   // Skip any lookup work until we hit the (possibly non-masking) interceptor.
    2313      601830 :   while (it.state() != LookupIterator::INTERCEPTOR ||
    2314      401220 :          !it.GetHolder<JSObject>().is_identical_to(holder)) {
    2315             :     DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
    2316           0 :     it.Next();
    2317             :   }
    2318             :   // Skip past the interceptor.
    2319      200610 :   it.Next();
    2320      401220 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
    2321             : 
    2322      200598 :   if (it.IsFound()) return *result;
    2323             : 
    2324        6437 :   Handle<Smi> slot = args.at<Smi>(3);
    2325        6437 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(4);
    2326        6437 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2327        6437 :   FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
    2328             :   // It could actually be any kind of load IC slot here but the predicate
    2329             :   // handles all the cases properly.
    2330        6437 :   if (!LoadIC::ShouldThrowReferenceError(slot_kind)) {
    2331        6305 :     return isolate->heap()->undefined_value();
    2332             :   }
    2333             : 
    2334             :   // Throw a reference error.
    2335         396 :   THROW_NEW_ERROR_RETURN_FAILURE(
    2336      279516 :       isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
    2337             : }
    2338             : 
    2339             : 
    2340     1092608 : RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
    2341      546304 :   HandleScope scope(isolate);
    2342             :   DCHECK_EQ(5, args.length());
    2343             :   // Runtime functions don't follow the IC's calling convention.
    2344      546304 :   Handle<Object> value = args.at(0);
    2345      546304 :   Handle<Smi> slot = args.at<Smi>(1);
    2346      546304 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2347      546304 :   Handle<JSObject> receiver = args.at<JSObject>(3);
    2348      546304 :   Handle<Name> name = args.at<Name>(4);
    2349      546304 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2350      546304 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2351             : 
    2352             :   DCHECK(receiver->HasNamedInterceptor());
    2353      546304 :   InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
    2354             :   DCHECK(!interceptor->non_masking());
    2355             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2356     1092608 :                                       *receiver, Object::DONT_THROW);
    2357             : 
    2358             :   v8::GenericNamedPropertySetterCallback setter =
    2359             :       v8::ToCData<v8::GenericNamedPropertySetterCallback>(
    2360      546304 :           interceptor->setter());
    2361      546304 :   Handle<Object> result = arguments.Call(setter, name, value);
    2362      546304 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2363      546298 :   if (!result.is_null()) return *value;
    2364             : 
    2365      300252 :   LookupIterator it(receiver, name, receiver);
    2366             :   // Skip past any access check on the receiver.
    2367      300252 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
    2368             :     DCHECK(it.HasAccess());
    2369           0 :     it.Next();
    2370             :   }
    2371             :   // Skip past the interceptor on the receiver.
    2372             :   DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
    2373      300252 :   it.Next();
    2374             : 
    2375      300252 :   MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
    2376             :                                    JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
    2377             :                isolate->heap()->exception());
    2378      546304 :   return *value;
    2379             : }
    2380             : 
    2381             : 
    2382        4464 : RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
    2383             :   // TODO(verwaest): This should probably get the holder and receiver as input.
    2384        2232 :   HandleScope scope(isolate);
    2385        2232 :   Handle<JSObject> receiver = args.at<JSObject>(0);
    2386             :   DCHECK_GE(args.smi_at(1), 0);
    2387        2232 :   uint32_t index = args.smi_at(1);
    2388             : 
    2389        2232 :   InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
    2390             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2391        4464 :                                       *receiver, Object::DONT_THROW);
    2392             : 
    2393             :   v8::IndexedPropertyGetterCallback getter =
    2394        2232 :       v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
    2395        2232 :   Handle<Object> result = arguments.Call(getter, index);
    2396             : 
    2397        2232 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2398             : 
    2399        2232 :   if (result.is_null()) {
    2400           0 :     LookupIterator it(isolate, receiver, index, receiver);
    2401             :     DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
    2402           0 :     it.Next();
    2403           0 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
    2404             :                                        Object::GetProperty(&it));
    2405             :   }
    2406             : 
    2407        2232 :   return *result;
    2408             : }
    2409             : }  // namespace internal
    2410             : }  // namespace v8

Generated by: LCOV version 1.10