LCOV - code coverage report
Current view: top level - src/ic - ic.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1090 1234 88.3 %
Date: 2017-04-26 Functions: 78 102 76.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/codegen.h"
      13             : #include "src/conversions.h"
      14             : #include "src/execution.h"
      15             : #include "src/field-type.h"
      16             : #include "src/frames-inl.h"
      17             : #include "src/ic/call-optimization.h"
      18             : #include "src/ic/handler-compiler.h"
      19             : #include "src/ic/handler-configuration-inl.h"
      20             : #include "src/ic/ic-inl.h"
      21             : #include "src/ic/ic-stats.h"
      22             : #include "src/ic/stub-cache.h"
      23             : #include "src/isolate-inl.h"
      24             : #include "src/macro-assembler.h"
      25             : #include "src/prototype.h"
      26             : #include "src/runtime-profiler.h"
      27             : #include "src/runtime/runtime-utils.h"
      28             : #include "src/runtime/runtime.h"
      29             : #include "src/tracing/trace-event.h"
      30             : #include "src/tracing/tracing-category-observer.h"
      31             : 
      32             : namespace v8 {
      33             : namespace internal {
      34             : 
      35           0 : char IC::TransitionMarkFromState(IC::State state) {
      36           0 :   switch (state) {
      37             :     case UNINITIALIZED:
      38             :       return '0';
      39             :     case PREMONOMORPHIC:
      40           0 :       return '.';
      41             :     case MONOMORPHIC:
      42           0 :       return '1';
      43             :     case RECOMPUTE_HANDLER:
      44           0 :       return '^';
      45             :     case POLYMORPHIC:
      46           0 :       return 'P';
      47             :     case MEGAMORPHIC:
      48           0 :       return 'N';
      49             :     case GENERIC:
      50           0 :       return 'G';
      51             :   }
      52           0 :   UNREACHABLE();
      53             :   return 0;
      54             : }
      55             : 
      56             : 
      57           0 : const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
      58           0 :   if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
      59           0 :   if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
      60             :     return ".IGNORE_OOB";
      61             :   }
      62           0 :   if (IsGrowStoreMode(mode)) return ".GROW";
      63           0 :   return "";
      64             : }
      65             : 
      66             : #define TRACE_GENERIC_IC(reason) set_slow_stub_reason(reason);
      67             : 
      68    13450565 : void IC::TraceIC(const char* type, Handle<Object> name) {
      69    13450565 :   if (FLAG_ic_stats) {
      70    13450565 :     if (AddressIsDeoptimizedCode()) return;
      71           0 :     State new_state = nexus()->StateFromFeedback();
      72           0 :     TraceIC(type, name, state(), new_state);
      73             :   }
      74             : }
      75             : 
      76           0 : Address IC::GetAbstractPC(int* line, int* column) const {
      77           0 :   JavaScriptFrameIterator it(isolate());
      78             : 
      79             :   JavaScriptFrame* frame = it.frame();
      80             :   DCHECK(!frame->is_builtin());
      81           0 :   int position = frame->position();
      82             : 
      83           0 :   Object* maybe_script = frame->function()->shared()->script();
      84           0 :   if (maybe_script->IsScript()) {
      85             :     Handle<Script> script(Script::cast(maybe_script), isolate());
      86             :     Script::PositionInfo info;
      87           0 :     Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET);
      88           0 :     *line = info.line + 1;
      89           0 :     *column = info.column + 1;
      90             :   } else {
      91           0 :     *line = position;
      92           0 :     *column = -1;
      93             :   }
      94             : 
      95           0 :   if (frame->is_interpreted()) {
      96             :     InterpretedFrame* iframe = static_cast<InterpretedFrame*>(frame);
      97             :     Address bytecode_start =
      98           0 :         reinterpret_cast<Address>(iframe->GetBytecodeArray()) - kHeapObjectTag +
      99           0 :         BytecodeArray::kHeaderSize;
     100           0 :     return bytecode_start + iframe->GetBytecodeOffset();
     101             :   }
     102             : 
     103           0 :   return frame->pc();
     104             : }
     105             : 
     106           0 : void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
     107           0 :                  State new_state) {
     108           0 :   if (V8_LIKELY(!FLAG_ic_stats)) return;
     109             : 
     110             :   Map* map = nullptr;
     111           0 :   if (!receiver_map().is_null()) {
     112             :     map = *receiver_map();
     113             :   }
     114             : 
     115             :   const char* modifier = "";
     116           0 :   if (IsKeyedStoreIC()) {
     117             :     KeyedAccessStoreMode mode =
     118           0 :         casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
     119             :     modifier = GetTransitionMarkModifier(mode);
     120             :   }
     121             : 
     122           0 :   if (!(FLAG_ic_stats &
     123             :         v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING)) {
     124             :     int line;
     125             :     int column;
     126           0 :     Address pc = GetAbstractPC(&line, &column);
     127           0 :     LOG(isolate(), ICEvent(type, is_keyed(), pc, line, column, map, *name,
     128             :                            TransitionMarkFromState(old_state),
     129             :                            TransitionMarkFromState(new_state), modifier,
     130             :                            slow_stub_reason_));
     131             :     return;
     132             :   }
     133             : 
     134           0 :   ICStats::instance()->Begin();
     135             :   ICInfo& ic_info = ICStats::instance()->Current();
     136           0 :   ic_info.type = is_keyed() ? "Keyed" : "";
     137             :   ic_info.type += type;
     138             : 
     139             :   Object* maybe_function =
     140           0 :       Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
     141             :   DCHECK(maybe_function->IsJSFunction());
     142             :   JSFunction* function = JSFunction::cast(maybe_function);
     143             :   int code_offset = 0;
     144           0 :   if (function->IsInterpreted()) {
     145           0 :     code_offset = InterpretedFrame::GetBytecodeOffset(fp());
     146             :   } else {
     147             :     code_offset =
     148           0 :         static_cast<int>(pc() - function->code()->instruction_start());
     149             :   }
     150             :   JavaScriptFrame::CollectFunctionAndOffsetForICStats(
     151           0 :       function, function->abstract_code(), code_offset);
     152             : 
     153             :   // Reserve enough space for IC transition state, the longest length is 17.
     154           0 :   ic_info.state.reserve(17);
     155             :   ic_info.state = "(";
     156           0 :   ic_info.state += TransitionMarkFromState(old_state);
     157             :   ic_info.state += "->";
     158           0 :   ic_info.state += TransitionMarkFromState(new_state);
     159             :   ic_info.state += modifier;
     160             :   ic_info.state += ")";
     161           0 :   ic_info.map = reinterpret_cast<void*>(map);
     162           0 :   if (map != nullptr) {
     163           0 :     ic_info.is_dictionary_map = map->is_dictionary_map();
     164           0 :     ic_info.number_of_own_descriptors = map->NumberOfOwnDescriptors();
     165           0 :     ic_info.instance_type = std::to_string(map->instance_type());
     166             :   }
     167             :   // TODO(lpy) Add name as key field in ICStats.
     168           0 :   ICStats::instance()->End();
     169             : }
     170             : 
     171             : 
     172             : #define TRACE_IC(type, name) TraceIC(type, name)
     173             : 
     174    14598146 : IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
     175             :     : isolate_(isolate),
     176             :       vector_set_(false),
     177             :       kind_(FeedbackSlotKind::kInvalid),
     178             :       target_maps_set_(false),
     179             :       slow_stub_reason_(nullptr),
     180    29196292 :       nexus_(nexus) {
     181             :   // To improve the performance of the (much used) IC code, we unfold a few
     182             :   // levels of the stack frame iteration code. This yields a ~35% speedup when
     183             :   // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
     184    14598146 :   const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
     185             :   Address* constant_pool = NULL;
     186             :   if (FLAG_enable_embedded_constant_pool) {
     187             :     constant_pool = reinterpret_cast<Address*>(
     188             :         entry + ExitFrameConstants::kConstantPoolOffset);
     189             :   }
     190             :   Address* pc_address =
     191    14598146 :       reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
     192    14598146 :   Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
     193             :   // If there's another JavaScript frame on the stack or a
     194             :   // StubFailureTrampoline, we need to look one frame further down the stack to
     195             :   // find the frame pointer and the return address stack slot.
     196    14598146 :   if (depth == EXTRA_CALL_FRAME) {
     197             :     if (FLAG_enable_embedded_constant_pool) {
     198             :       constant_pool = reinterpret_cast<Address*>(
     199             :           fp + StandardFrameConstants::kConstantPoolOffset);
     200             :     }
     201             :     const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
     202      841413 :     pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
     203      841413 :     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
     204             :   }
     205             : #ifdef DEBUG
     206             :   StackFrameIterator it(isolate);
     207             :   for (int i = 0; i < depth + 1; i++) it.Advance();
     208             :   StackFrame* frame = it.frame();
     209             :   DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
     210             : #endif
     211             :   // For interpreted functions, some bytecode handlers construct a
     212             :   // frame. We have to skip the constructed frame to find the interpreted
     213             :   // function's frame. Check if the there is an additional frame, and if there
     214             :   // is skip this frame. However, the pc should not be updated. The call to
     215             :   // ICs happen from bytecode handlers.
     216             :   intptr_t frame_marker =
     217    14598146 :       Memory::intptr_at(fp + TypedFrameConstants::kFrameTypeOffset);
     218    14598146 :   if (frame_marker == StackFrame::TypeToMarker(StackFrame::STUB)) {
     219     9080537 :     fp = Memory::Address_at(fp + TypedFrameConstants::kCallerFPOffset);
     220             :   }
     221    14598146 :   fp_ = fp;
     222             :   if (FLAG_enable_embedded_constant_pool) {
     223             :     constant_pool_address_ = constant_pool;
     224             :   }
     225    14598146 :   pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
     226    14598146 :   if (nexus) {
     227    13756733 :     kind_ = nexus->kind();
     228    13756737 :     state_ = nexus->StateFromFeedback();
     229    13756733 :     extra_ic_state_ = kNoExtraICState;
     230             :   } else {
     231      841413 :     Code* target = this->target();
     232             :     Code::Kind kind = target->kind();
     233      841413 :     if (kind == Code::BINARY_OP_IC) {
     234      437808 :       kind_ = FeedbackSlotKind::kBinaryOp;
     235      403605 :     } else if (kind == Code::COMPARE_IC) {
     236      272912 :       kind_ = FeedbackSlotKind::kCompareOp;
     237      130693 :     } else if (kind == Code::TO_BOOLEAN_IC) {
     238      130693 :       kind_ = FeedbackSlotKind::kToBoolean;
     239             :     } else {
     240           0 :       UNREACHABLE();
     241             :       kind_ = FeedbackSlotKind::kInvalid;
     242             :     }
     243      841413 :     state_ = StateFromCode(target);
     244      841413 :     extra_ic_state_ = target->extra_ic_state();
     245             :   }
     246    14598146 :   old_state_ = state_;
     247    14598146 : }
     248             : 
     249             : // The ICs that don't pass slot and vector through the stack have to
     250             : // save/restore them in the dispatcher.
     251       77396 : bool IC::ShouldPushPopSlotAndVector(Code::Kind kind) {
     252       77396 :   if (kind == Code::LOAD_IC || kind == Code::LOAD_GLOBAL_IC ||
     253             :       kind == Code::KEYED_LOAD_IC) {
     254             :     return true;
     255             :   }
     256       76842 :   if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
     257             :     return !StoreWithVectorDescriptor::kPassLastArgsOnStack;
     258             :   }
     259           0 :   return false;
     260             : }
     261             : 
     262     2516237 : InlineCacheState IC::StateFromCode(Code* code) {
     263             :   Isolate* isolate = code->GetIsolate();
     264     2516237 :   switch (code->kind()) {
     265             :     case Code::BINARY_OP_IC: {
     266     1305418 :       BinaryOpICState state(isolate, code->extra_ic_state());
     267     1305418 :       return state.GetICState();
     268             :     }
     269             :     case Code::COMPARE_IC: {
     270             :       CompareICStub stub(isolate, code->extra_ic_state());
     271      818740 :       return stub.GetICState();
     272             :     }
     273             :     case Code::TO_BOOLEAN_IC: {
     274             :       ToBooleanICStub stub(isolate, code->extra_ic_state());
     275             :       return stub.GetICState();
     276             :     }
     277             :     default:
     278           0 :       if (code->is_debug_stub()) return UNINITIALIZED;
     279           0 :       UNREACHABLE();
     280             :       return UNINITIALIZED;
     281             :   }
     282             : }
     283             : 
     284    38031045 : JSFunction* IC::GetHostFunction() const {
     285             :   // Compute the JavaScript frame for the frame pointer of this IC
     286             :   // structure. We need this to be able to find the function
     287             :   // corresponding to the frame.
     288    10447462 :   StackFrameIterator it(isolate());
     289    38031046 :   while (it.frame()->fp() != this->fp()) it.Advance();
     290             :   JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
     291             :   // Find the function on the stack and both the active code for the
     292             :   // function and the original code.
     293    20894918 :   return frame->function();
     294             : }
     295             : 
     296    13392844 : static void LookupForRead(LookupIterator* it) {
     297    13431098 :   for (; it->IsFound(); it->Next()) {
     298     6281840 :     switch (it->state()) {
     299             :       case LookupIterator::NOT_FOUND:
     300             :       case LookupIterator::TRANSITION:
     301           0 :         UNREACHABLE();
     302             :       case LookupIterator::JSPROXY:
     303             :         return;
     304             :       case LookupIterator::INTERCEPTOR: {
     305             :         // If there is a getter, return; otherwise loop to perform the lookup.
     306             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
     307        2560 :         if (!holder->GetNamedInterceptor()->getter()->IsUndefined(
     308        2560 :                 it->isolate())) {
     309             :           return;
     310             :         }
     311             :         break;
     312             :       }
     313             :       case LookupIterator::ACCESS_CHECK:
     314             :         // ICs know how to perform access checks on global proxies.
     315       41067 :         if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
     316             :           break;
     317             :         }
     318             :         return;
     319             :       case LookupIterator::ACCESSOR:
     320             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
     321             :       case LookupIterator::DATA:
     322             :         return;
     323             :     }
     324             :   }
     325             : }
     326             : 
     327     6647276 : bool IC::ShouldRecomputeHandler(Handle<String> name) {
     328     2232162 :   if (!RecomputeHandlerForName(name)) return false;
     329             : 
     330     2207557 :   maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
     331             : 
     332             :   // This is a contextual access, always just update the handler and stay
     333             :   // monomorphic.
     334     2207557 :   if (IsLoadGlobalIC()) return true;
     335             : 
     336             :   // The current map wasn't handled yet. There's no reason to stay monomorphic,
     337             :   // *unless* we're moving from a deprecated map to its replacement, or
     338             :   // to a more general elements kind.
     339             :   // TODO(verwaest): Check if the current map is actually what the old map
     340             :   // would transition to.
     341     2206753 :   if (maybe_handler_.is_null()) {
     342     2096521 :     if (!receiver_map()->IsJSObjectMap()) return false;
     343     2084025 :     Map* first_map = FirstTargetMap();
     344     2084025 :     if (first_map == NULL) return false;
     345             :     Handle<Map> old_map(first_map);
     346      701348 :     if (old_map->is_deprecated()) return true;
     347             :     return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
     348      472530 :                                                receiver_map()->elements_kind());
     349             :   }
     350             : 
     351             :   return true;
     352             : }
     353             : 
     354     2264072 : bool IC::RecomputeHandlerForName(Handle<Object> name) {
     355     2232162 :   if (is_keyed()) {
     356             :     // Determine whether the failure is due to a name failure.
     357       31910 :     if (!name->IsName()) return false;
     358       31910 :     Name* stub_name = nexus()->FindFirstName();
     359       31910 :     if (*name != stub_name) return false;
     360             :   }
     361             : 
     362             :   return true;
     363             : }
     364             : 
     365             : 
     366    28781736 : void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
     367    13756733 :   update_receiver_map(receiver);
     368    13756733 :   if (!name->IsString()) return;
     369    12792623 :   if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
     370     2232380 :   if (receiver->IsNullOrUndefined(isolate())) return;
     371             : 
     372             :   // Remove the target from the code cache if it became invalid
     373             :   // because of changes in the prototype chain to avoid hitting it
     374             :   // again.
     375     2232162 :   if (ShouldRecomputeHandler(Handle<String>::cast(name))) {
     376             :     MarkRecomputeHandler(name);
     377             :   }
     378             : }
     379             : 
     380             : 
     381        3468 : MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
     382        3468 :                                   Handle<Object> object, Handle<Object> key) {
     383             :   HandleScope scope(isolate());
     384       10404 :   THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
     385             : }
     386             : 
     387             : 
     388      140293 : MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
     389             :   HandleScope scope(isolate());
     390      420879 :   THROW_NEW_ERROR(
     391             :       isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
     392             : }
     393             : 
     394             : 
     395      764022 : static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
     396             :                                       int* polymorphic_delta,
     397             :                                       int* generic_delta) {
     398      764022 :   switch (old_state) {
     399             :     case UNINITIALIZED:
     400             :     case PREMONOMORPHIC:
     401      723801 :       if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
     402      723801 :       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
     403      712489 :         *polymorphic_delta = 1;
     404       11312 :       } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
     405       11312 :         *generic_delta = 1;
     406             :       }
     407             :       break;
     408             :     case MONOMORPHIC:
     409             :     case POLYMORPHIC:
     410       40148 :       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
     411       13250 :       *polymorphic_delta = -1;
     412       13250 :       if (new_state == MEGAMORPHIC || new_state == GENERIC) {
     413       13248 :         *generic_delta = 1;
     414             :       }
     415             :       break;
     416             :     case MEGAMORPHIC:
     417             :     case GENERIC:
     418          73 :       if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
     419           0 :       *generic_delta = -1;
     420           0 :       if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
     421           0 :         *polymorphic_delta = 1;
     422             :       }
     423             :       break;
     424             :     case RECOMPUTE_HANDLER:
     425           0 :       UNREACHABLE();
     426             :   }
     427      764022 : }
     428             : 
     429             : // static
     430    20781286 : void IC::OnFeedbackChanged(Isolate* isolate, JSFunction* host_function) {
     431             :   Code* host = host_function->shared()->code();
     432             : 
     433    10390643 :   if (host->kind() == Code::FUNCTION) {
     434             :     TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
     435             :     info->change_own_type_change_checksum();
     436             :     host->set_profiler_ticks(0);
     437     7177312 :   } else if (host_function->IsInterpreted()) {
     438     6645899 :     if (FLAG_trace_opt_verbose) {
     439           0 :       if (host_function->shared()->profiler_ticks() != 0) {
     440           0 :         PrintF("[resetting ticks for ");
     441           0 :         host_function->PrintName();
     442             :         PrintF(" due from %d due to IC change]\n",
     443           0 :                host_function->shared()->profiler_ticks());
     444             :       }
     445             :     }
     446             :     host_function->shared()->set_profiler_ticks(0);
     447             :   }
     448             :   isolate->runtime_profiler()->NotifyICChanged();
     449             :   // TODO(2029): When an optimized function is patched, it would
     450             :   // be nice to propagate the corresponding type information to its
     451             :   // unoptimized version for the benefit of later inlining.
     452    10390643 : }
     453             : 
     454      837412 : void IC::PostPatching(Address address, Code* target, Code* old_target) {
     455             :   // Type vector based ICs update these statistics at a different time because
     456             :   // they don't always patch on state change.
     457             :   DCHECK(target->kind() == Code::BINARY_OP_IC ||
     458             :          target->kind() == Code::COMPARE_IC ||
     459             :          target->kind() == Code::TO_BOOLEAN_IC);
     460             : 
     461             :   DCHECK(old_target->is_inline_cache_stub());
     462             :   DCHECK(target->is_inline_cache_stub());
     463      837412 :   State old_state = StateFromCode(old_target);
     464      837412 :   State new_state = StateFromCode(target);
     465             : 
     466     1601434 :   Isolate* isolate = target->GetIsolate();
     467             :   Code* host =
     468      837412 :       isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
     469     1674824 :   if (host->kind() != Code::FUNCTION) return;
     470             : 
     471             :   // Not all Code objects have TypeFeedbackInfo.
     472      764022 :   if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
     473      764022 :     if (FLAG_type_info_threshold > 0) {
     474      764022 :       int polymorphic_delta = 0;  // "Polymorphic" here includes monomorphic.
     475      764022 :       int generic_delta = 0;      // "Generic" here includes megamorphic.
     476             :       ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
     477      764022 :                                 &generic_delta);
     478             :       TypeFeedbackInfo* info =
     479             :           TypeFeedbackInfo::cast(host->type_feedback_info());
     480      764022 :       info->change_ic_with_type_info_count(polymorphic_delta);
     481      764022 :       info->change_ic_generic_count(generic_delta);
     482             :     }
     483             :     TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
     484             :     info->change_own_type_change_checksum();
     485             :   }
     486             :   host->set_profiler_ticks(0);
     487             :   isolate->runtime_profiler()->NotifyICChanged();
     488             :   // TODO(2029): When an optimized function is patched, it would
     489             :   // be nice to propagate the corresponding type information to its
     490             :   // unoptimized version for the benefit of later inlining.
     491             : }
     492             : 
     493      132634 : void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
     494      132634 :   Code* target = GetTargetAtAddress(address, constant_pool);
     495             : 
     496             :   // Don't clear debug break inline cache as it will remove the break point.
     497      265268 :   if (target->is_debug_stub()) return;
     498             : 
     499      132634 :   if (target->kind() == Code::COMPARE_IC) {
     500        5029 :     CompareIC::Clear(isolate, address, target, constant_pool);
     501             :   }
     502             : }
     503             : 
     504        5029 : void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
     505             :                       Address constant_pool) {
     506             :   DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
     507             :   CompareICStub stub(target->stub_key(), isolate);
     508             :   // Only clear CompareICs that can retain objects.
     509       10058 :   if (stub.state() != CompareICState::KNOWN_RECEIVER) return;
     510             :   SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()),
     511           2 :                      constant_pool);
     512           2 :   PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
     513             : }
     514             : 
     515    14261528 : static bool MigrateDeprecated(Handle<Object> object) {
     516    14261528 :   if (!object->IsJSObject()) return false;
     517             :   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
     518    14019054 :   if (!receiver->map()->is_deprecated()) return false;
     519        7435 :   JSObject::MigrateInstance(Handle<JSObject>::cast(object));
     520        7435 :   return true;
     521             : }
     522             : 
     523    15151794 : void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
     524     5050598 :   if (new_state == PREMONOMORPHIC) {
     525     4945078 :     nexus()->ConfigurePremonomorphic();
     526      105520 :   } else if (new_state == MEGAMORPHIC) {
     527             :     DCHECK_IMPLIES(!is_keyed(), key->IsName());
     528      211040 :     nexus()->ConfigureMegamorphic(key->IsName() ? PROPERTY : ELEMENT);
     529             :   } else {
     530           0 :     UNREACHABLE();
     531             :   }
     532             : 
     533     5050599 :   vector_set_ = true;
     534    10101197 :   OnFeedbackChanged(isolate(), GetHostFunction());
     535     5050598 : }
     536             : 
     537     4736345 : void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
     538    14209034 :                               Handle<Object> handler) {
     539     4736345 :   if (IsLoadGlobalIC()) {
     540             :     LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
     541       59462 :     nexus->ConfigureHandlerMode(handler);
     542             :   } else {
     543             :     // Non-keyed ICs don't track the name explicitly.
     544     4676883 :     if (!is_keyed()) name = Handle<Name>::null();
     545     4676883 :     nexus()->ConfigureMonomorphic(name, map, handler);
     546             :   }
     547             : 
     548     4736347 :   vector_set_ = true;
     549     9472691 :   OnFeedbackChanged(isolate(), GetHostFunction());
     550     4736344 : }
     551             : 
     552      553319 : void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
     553     1106638 :                               List<Handle<Object>>* handlers) {
     554             :   DCHECK(!IsLoadGlobalIC());
     555             :   // Non-keyed ICs don't track the name explicitly.
     556      553319 :   if (!is_keyed()) name = Handle<Name>::null();
     557      553319 :   nexus()->ConfigurePolymorphic(name, maps, handlers);
     558             : 
     559      553319 :   vector_set_ = true;
     560     1106638 :   OnFeedbackChanged(isolate(), GetHostFunction());
     561      553319 : }
     562             : 
     563     6678125 : MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
     564             :   // If the object is undefined or null it's illegal to try to get any
     565             :   // of its properties; throw a TypeError in that case.
     566    24259698 :   if (object->IsNullOrUndefined(isolate())) {
     567        6788 :     if (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
     568             :       // Ensure the IC state progresses.
     569         245 :       TRACE_HANDLER_STATS(isolate(), LoadIC_NonReceiver);
     570         245 :       update_receiver_map(object);
     571         490 :       PatchCache(name, slow_stub());
     572         245 :       TRACE_IC("LoadIC", name);
     573             :     }
     574        3394 :     return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
     575             :   }
     576             : 
     577     6674734 :   bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
     578             : 
     579     6674733 :   if (state() != UNINITIALIZED) {
     580     3930995 :     JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
     581     3930995 :     update_receiver_map(object);
     582             :   }
     583             :   // Named lookup in the object.
     584     6674733 :   LookupIterator it(object, name);
     585     6674735 :   LookupForRead(&it);
     586             : 
     587     7108444 :   if (it.IsFound() || !ShouldThrowReferenceError()) {
     588             :     // Update inline cache and stub cache.
     589     6535113 :     if (use_ic) UpdateCaches(&it);
     590             : 
     591             :     // Get the property.
     592             :     Handle<Object> result;
     593             : 
     594    13070228 :     ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
     595             :                                Object);
     596     6532867 :     if (it.IsFound()) {
     597             :       return result;
     598      294358 :     } else if (!ShouldThrowReferenceError()) {
     599      294323 :       LOG(isolate(), SuspectReadEvent(*name, *object));
     600             :       return result;
     601             :     }
     602             :   }
     603      139657 :   return ReferenceError(name);
     604             : }
     605             : 
     606     2094578 : MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
     607     2262182 :   Handle<JSGlobalObject> global = isolate()->global_object();
     608             : 
     609     2094580 :   if (name->IsString()) {
     610             :     // Look up in script context table.
     611     2094579 :     Handle<String> str_name = Handle<String>::cast(name);
     612             :     Handle<ScriptContextTable> script_contexts(
     613             :         global->native_context()->script_context_table());
     614             : 
     615             :     ScriptContextTable::LookupResult lookup_result;
     616     2094580 :     if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
     617             :       Handle<Object> result =
     618             :           FixedArray::get(*ScriptContextTable::GetContext(
     619      112148 :                               script_contexts, lookup_result.context_index),
     620      112148 :                           lookup_result.slot_index, isolate());
     621       56074 :       if (result->IsTheHole(isolate())) {
     622             :         // Do not install stubs and stay pre-monomorphic for
     623             :         // uninitialized accesses.
     624         618 :         return ReferenceError(name);
     625             :       }
     626             : 
     627      110912 :       if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
     628       55456 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
     629             :         LoadScriptContextFieldStub stub(isolate(), &lookup_result);
     630      110912 :         PatchCache(name, stub.GetCode());
     631       55456 :         TRACE_IC("LoadGlobalIC", name);
     632             :       }
     633             :       return result;
     634             :     }
     635             :   }
     636     2038507 :   return LoadIC::Load(global, name);
     637             : }
     638             : 
     639      176232 : static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
     640             :                                        Handle<Map> new_receiver_map) {
     641             :   DCHECK(!new_receiver_map.is_null());
     642      243860 :   for (int current = 0; current < receiver_maps->length(); ++current) {
     643      166546 :     if (!receiver_maps->at(current).is_null() &&
     644             :         receiver_maps->at(current).is_identical_to(new_receiver_map)) {
     645             :       return false;
     646             :     }
     647             :   }
     648       38657 :   receiver_maps->Add(new_receiver_map);
     649       38657 :   return true;
     650             : }
     651             : 
     652     5746877 : bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
     653             :   DCHECK(IsHandler(*handler));
     654     2198616 :   if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
     655     2198377 :   Handle<Map> map = receiver_map();
     656             :   MapHandleList maps;
     657             :   List<Handle<Object>> handlers;
     658             : 
     659     2198377 :   TargetMaps(&maps);
     660     2198377 :   int number_of_maps = maps.length();
     661             :   int deprecated_maps = 0;
     662             :   int handler_to_overwrite = -1;
     663             : 
     664     3501657 :   for (int i = 0; i < number_of_maps; i++) {
     665     1303280 :     Handle<Map> current_map = maps.at(i);
     666     1303280 :     if (current_map->is_deprecated()) {
     667             :       // Filter out deprecated maps to ensure their instances get migrated.
     668      294280 :       ++deprecated_maps;
     669     1009000 :     } else if (map.is_identical_to(current_map)) {
     670             :       // If the receiver type is already in the polymorphic IC, this indicates
     671             :       // there was a prototoype chain failure. In that case, just overwrite the
     672             :       // handler.
     673             :       handler_to_overwrite = i;
     674     1773078 :     } else if (handler_to_overwrite == -1 &&
     675      873004 :                IsTransitionOfMonomorphicTarget(*current_map, *map)) {
     676             :       handler_to_overwrite = i;
     677             :     }
     678             :   }
     679             : 
     680             :   int number_of_valid_maps =
     681     2198377 :       number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
     682             : 
     683     2198377 :   if (number_of_valid_maps >= kMaxPolymorphicMapCount) return false;
     684     3548261 :   if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
     685             :     return false;
     686             :   }
     687     2167575 :   if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
     688             : 
     689     2167575 :   number_of_valid_maps++;
     690     2686796 :   if (number_of_valid_maps > 1 && is_keyed()) return false;
     691     2167559 :   if (number_of_valid_maps == 1) {
     692     1648354 :     ConfigureVectorState(name, receiver_map(), handler);
     693             :   } else {
     694      519205 :     if (handler_to_overwrite >= 0) {
     695       30133 :       handlers.Set(handler_to_overwrite, handler);
     696       30133 :       if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
     697             :         maps.Set(handler_to_overwrite, map);
     698             :       }
     699             :     } else {
     700      489072 :       maps.Add(map);
     701      489072 :       handlers.Add(handler);
     702             :     }
     703             : 
     704      519205 :     ConfigureVectorState(name, &maps, &handlers);
     705             :   }
     706             : 
     707             :   return true;
     708             : }
     709             : 
     710           0 : void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
     711             :   DCHECK(IsHandler(*handler));
     712     2473780 :   ConfigureVectorState(name, receiver_map(), handler);
     713           0 : }
     714             : 
     715             : 
     716       61636 : void IC::CopyICToMegamorphicCache(Handle<Name> name) {
     717             :   MapHandleList maps;
     718             :   List<Handle<Object>> handlers;
     719       30818 :   TargetMaps(&maps);
     720       61636 :   if (!nexus()->FindHandlers(&handlers, maps.length())) return;
     721      123542 :   for (int i = 0; i < maps.length(); i++) {
     722      123542 :     UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
     723             :   }
     724             : }
     725             : 
     726             : 
     727      892025 : bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
     728      892025 :   if (source_map == NULL) return true;
     729      892025 :   if (target_map == NULL) return false;
     730             :   ElementsKind target_elements_kind = target_map->elements_kind();
     731             :   bool more_general_transition = IsMoreGeneralElementsKindTransition(
     732      892025 :       source_map->elements_kind(), target_elements_kind);
     733             :   Map* transitioned_map = nullptr;
     734      892025 :   if (more_general_transition) {
     735             :     MapHandleList map_list;
     736       25003 :     map_list.Add(handle(target_map));
     737       25003 :     transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list);
     738             :   }
     739      892025 :   return transitioned_map == target_map;
     740             : }
     741             : 
     742     7847624 : void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
     743             :   DCHECK(IsHandler(*handler));
     744             :   // Currently only load and store ICs support non-code handlers.
     745             :   DCHECK(IsAnyLoad() || IsAnyStore());
     746     5921509 :   switch (state()) {
     747             :     case UNINITIALIZED:
     748             :     case PREMONOMORPHIC:
     749             :       UpdateMonomorphicIC(handler, name);
     750             :       break;
     751             :     case RECOMPUTE_HANDLER:
     752             :     case MONOMORPHIC:
     753     1926115 :       if (IsLoadGlobalIC()) {
     754             :         UpdateMonomorphicIC(handler, name);
     755             :         break;
     756             :       }
     757             :     // Fall through.
     758             :     case POLYMORPHIC:
     759     2232088 :       if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
     760     2198377 :         if (UpdatePolymorphicIC(name, handler)) break;
     761             :         // For keyed stubs, we can't know whether old handlers were for the
     762             :         // same key.
     763       30818 :         CopyICToMegamorphicCache(name);
     764             :       }
     765       64529 :       ConfigureVectorState(MEGAMORPHIC, name);
     766             :     // Fall through.
     767             :     case MEGAMORPHIC:
     768     1280173 :       UpdateMegamorphicCache(*receiver_map(), *name, *handler);
     769             :       // Indicate that we've handled this case.
     770     1280173 :       vector_set_ = true;
     771     1280173 :       break;
     772             :     case GENERIC:
     773           0 :       UNREACHABLE();
     774             :       break;
     775             :   }
     776     5921509 : }
     777             : 
     778     2055965 : Handle<Smi> LoadIC::SimpleFieldLoad(Isolate* isolate, FieldIndex index) {
     779     2055965 :   TRACE_HANDLER_STATS(isolate, LoadIC_LoadFieldDH);
     780     2055965 :   return LoadHandler::LoadField(isolate, index);
     781             : }
     782             : 
     783             : namespace {
     784             : 
     785             : template <bool fill_array = true>
     786     2824724 : int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
     787             :                         Handle<JSObject> holder, Handle<Name> name,
     788             :                         Handle<FixedArray> array, int first_index) {
     789     5150520 :   if (!holder.is_null() && holder->map() == *receiver_map) return 0;
     790             : 
     791             :   HandleScope scope(isolate);
     792             :   int checks_count = 0;
     793             : 
     794     5545572 :   if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap()) {
     795             :     // The validity cell check for primitive and global proxy receivers does
     796             :     // not guarantee that certain native context ever had access to other
     797             :     // native context. However, a handler created for one native context could
     798             :     // be used in other native context through the megamorphic stub cache.
     799             :     // So we record the original native context to which this handler
     800             :     // corresponds.
     801             :     if (fill_array) {
     802       55822 :       Handle<Context> native_context = isolate->native_context();
     803       55822 :       array->set(LoadHandler::kFirstPrototypeIndex + checks_count,
     804             :                  native_context->self_weak_cell());
     805             :     }
     806             :     checks_count++;
     807             : 
     808     2712417 :   } else if (receiver_map->IsJSGlobalObjectMap()) {
     809             :     // If we are creating a handler for [Load/Store]GlobalIC then we need to
     810             :     // check that the property did not appear in the global object.
     811             :     if (fill_array) {
     812        2192 :       Handle<JSGlobalObject> global = isolate->global_object();
     813             :       Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
     814        2192 :           global, name, PropertyCellType::kInvalidated);
     815             :       DCHECK(cell->value()->IsTheHole(isolate));
     816        2192 :       Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
     817        2192 :       array->set(LoadHandler::kFirstPrototypeIndex + checks_count, *weak_cell);
     818             :     }
     819             :     checks_count++;
     820             :   }
     821             : 
     822             :   // Create/count entries for each global or dictionary prototype appeared in
     823             :   // the prototype chain contains from receiver till holder.
     824     2824061 :   PrototypeIterator::WhereToEnd end = name->IsPrivate()
     825             :                                           ? PrototypeIterator::END_AT_NON_HIDDEN
     826     2824061 :                                           : PrototypeIterator::END_AT_NULL;
     827     9285664 :   for (PrototypeIterator iter(receiver_map, end); !iter.IsAtEnd();
     828     3637541 :        iter.Advance()) {
     829             :     Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
     830     5962662 :     if (holder.is_identical_to(current)) break;
     831             :     Handle<Map> current_map(current->map(), isolate);
     832             : 
     833     3637541 :     if (current_map->IsJSGlobalObjectMap()) {
     834             :       if (fill_array) {
     835        1257 :         Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
     836             :         Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
     837        1257 :             global, name, PropertyCellType::kInvalidated);
     838             :         DCHECK(cell->value()->IsTheHole(isolate));
     839        1257 :         Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
     840        2514 :         array->set(first_index + checks_count, *weak_cell);
     841             :       }
     842        2514 :       checks_count++;
     843             : 
     844     3635027 :     } else if (current_map->is_dictionary_map()) {
     845             :       DCHECK(!current_map->IsJSGlobalProxyMap());  // Proxy maps are fast.
     846             :       if (fill_array) {
     847             :         DCHECK_EQ(NameDictionary::kNotFound,
     848             :                   current->property_dictionary()->FindEntry(name));
     849             :         Handle<WeakCell> weak_cell =
     850         270 :             Map::GetOrCreatePrototypeWeakCell(current, isolate);
     851         540 :         array->set(first_index + checks_count, *weak_cell);
     852             :       }
     853         540 :       checks_count++;
     854             :     }
     855             :   }
     856             :   return checks_count;
     857             : }
     858             : 
     859             : // Returns 0 if the validity cell check is enough to ensure that the
     860             : // prototype chain from |receiver_map| till |holder| did not change.
     861             : // If the |holder| is an empty handle then the full prototype chain is
     862             : // checked.
     863             : // Returns -1 if the handler has to be compiled or the number of prototype
     864             : // checks otherwise.
     865             : int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
     866             :                            Handle<JSObject> holder, Handle<Name> name) {
     867             :   return InitPrototypeChecks<false>(isolate, receiver_map, holder, name,
     868     2765994 :                                     Handle<FixedArray>(), 0);
     869             : }
     870             : 
     871     1208737 : Handle<WeakCell> HolderCell(Isolate* isolate, Handle<JSObject> holder,
     872             :                             Handle<Name> name, Handle<Smi> smi_handler) {
     873     3626211 :   if (holder->IsJSGlobalObject() &&
     874     1246533 :       *smi_handler != *LoadHandler::LoadInterceptor(isolate)) {
     875             :     Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder);
     876             :     GlobalDictionary* dict = global->global_dictionary();
     877       18898 :     int number = dict->FindEntry(name);
     878             :     DCHECK_NE(NameDictionary::kNotFound, number);
     879             :     Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(number)),
     880       18898 :                               isolate);
     881       18898 :     return isolate->factory()->NewWeakCell(cell);
     882             :   }
     883     1189839 :   return Map::GetOrCreatePrototypeWeakCell(holder, isolate);
     884             : }
     885             : 
     886             : }  // namespace
     887             : 
     888     1208737 : Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
     889             :                                          Handle<JSObject> holder,
     890             :                                          Handle<Name> name,
     891             :                                          Handle<Smi> smi_handler) {
     892             :   int checks_count =
     893     4935458 :       GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
     894             :   DCHECK_LE(0, checks_count);
     895             : 
     896     2372784 :   if (receiver_map->IsPrimitiveMap() ||
     897             :       receiver_map->is_access_check_needed()) {
     898             :     DCHECK(!receiver_map->is_dictionary_map());
     899             :     DCHECK_LE(1, checks_count);  // For native context.
     900             :     smi_handler =
     901       49127 :         LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
     902     1162485 :   } else if (receiver_map->is_dictionary_map() &&
     903             :              !receiver_map->IsJSGlobalObjectMap()) {
     904        1259 :     smi_handler = LoadHandler::EnableLookupOnReceiver(isolate(), smi_handler);
     905             :   }
     906             : 
     907             :   Handle<Cell> validity_cell =
     908     1208737 :       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
     909             :   DCHECK(!validity_cell.is_null());
     910             : 
     911             :   Handle<WeakCell> holder_cell =
     912     1208737 :       HolderCell(isolate(), holder, name, smi_handler);
     913             : 
     914     1208737 :   if (checks_count == 0) {
     915             :     return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
     916     1158613 :                                            validity_cell);
     917             :   }
     918             :   Handle<FixedArray> handler_array(isolate()->factory()->NewFixedArray(
     919      100248 :       LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
     920             :   handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
     921       50124 :   handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
     922       50124 :   handler_array->set(LoadHandler::kHolderCellIndex, *holder_cell);
     923             :   InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
     924       50124 :                       LoadHandler::kFirstPrototypeIndex);
     925       50124 :   return handler_array;
     926             : }
     927             : 
     928      277625 : Handle<Object> LoadIC::LoadFullChain(Handle<Map> receiver_map,
     929             :                                      Handle<Object> holder, Handle<Name> name,
     930             :                                      Handle<Smi> smi_handler) {
     931             :   Handle<JSObject> end;  // null handle
     932      714495 :   int checks_count = GetPrototypeCheckCount(isolate(), receiver_map, end, name);
     933             :   DCHECK_LE(0, checks_count);
     934             : 
     935      548665 :   if (receiver_map->IsPrimitiveMap() ||
     936             :       receiver_map->is_access_check_needed()) {
     937             :     DCHECK(!receiver_map->is_dictionary_map());
     938             :     DCHECK_LE(1, checks_count);  // For native context.
     939             :     smi_handler =
     940        6695 :         LoadHandler::EnableAccessCheckOnReceiver(isolate(), smi_handler);
     941      273040 :   } else if (receiver_map->is_dictionary_map() &&
     942             :              !receiver_map->IsJSGlobalObjectMap()) {
     943         871 :     smi_handler = LoadHandler::EnableLookupOnReceiver(isolate(), smi_handler);
     944             :   }
     945             : 
     946             :   Handle<Object> validity_cell =
     947      277625 :       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
     948      277625 :   if (validity_cell.is_null()) {
     949             :     DCHECK_EQ(0, checks_count);
     950             :     // Lookup on receiver isn't supported in case of a simple smi handler.
     951      267954 :     if (!LoadHandler::LookupOnReceiverBits::decode(smi_handler->value())) {
     952      133950 :       return smi_handler;
     953             :     }
     954             :     validity_cell = handle(Smi::kZero, isolate());
     955             :   }
     956             : 
     957             :   Factory* factory = isolate()->factory();
     958      143675 :   if (checks_count == 0) {
     959      135698 :     return factory->NewTuple3(holder, smi_handler, validity_cell);
     960             :   }
     961             :   Handle<FixedArray> handler_array(factory->NewFixedArray(
     962        7977 :       LoadHandler::kFirstPrototypeIndex + checks_count, TENURED));
     963             :   handler_array->set(LoadHandler::kSmiHandlerIndex, *smi_handler);
     964        7977 :   handler_array->set(LoadHandler::kValidityCellIndex, *validity_cell);
     965        7977 :   handler_array->set(LoadHandler::kHolderCellIndex, *holder);
     966             :   InitPrototypeChecks(isolate(), receiver_map, end, name, handler_array,
     967        7977 :                       LoadHandler::kFirstPrototypeIndex);
     968        7977 :   return handler_array;
     969             : }
     970             : 
     971    14250095 : void LoadIC::UpdateCaches(LookupIterator* lookup) {
     972    17122355 :   if (state() == UNINITIALIZED && !IsLoadGlobalIC()) {
     973             :     // This is the first time we execute this inline cache. Set the target to
     974             :     // the pre monomorphic stub to delay setting the monomorphic state.
     975      703676 :     TRACE_HANDLER_STATS(isolate(), LoadIC_Premonomorphic);
     976      703676 :     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
     977      703676 :     TRACE_IC("LoadIC", lookup->name());
     978     3302051 :     return;
     979             :   }
     980             : 
     981             :   Handle<Object> code;
     982     5824490 :   if (lookup->state() == LookupIterator::JSPROXY ||
     983             :       lookup->state() == LookupIterator::ACCESS_CHECK) {
     984        4452 :     code = slow_stub();
     985     5820038 :   } else if (!lookup->IsFound()) {
     986      277560 :     TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonexistentDH);
     987      277560 :     Handle<Smi> smi_handler = LoadHandler::LoadNonExistent(isolate());
     988             :     code = LoadFullChain(receiver_map(), isolate()->factory()->null_value(),
     989      277560 :                          lookup->name(), smi_handler);
     990             :   } else {
     991     5542478 :     if (IsLoadGlobalIC()) {
     992     1897439 :       if (lookup->TryLookupCachedProperty()) {
     993             :         DCHECK_EQ(LookupIterator::DATA, lookup->state());
     994             :       }
     995     3792894 :       if (lookup->state() == LookupIterator::DATA &&
     996             :           lookup->GetReceiver().is_identical_to(lookup->GetHolder<Object>())) {
     997             :         DCHECK(lookup->GetReceiver()->IsJSGlobalObject());
     998             :         // Now update the cell in the feedback vector.
     999             :         LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
    1000     1894699 :         nexus->ConfigurePropertyCellMode(lookup->GetPropertyCell());
    1001     1894701 :         TRACE_IC("LoadGlobalIC", lookup->name());
    1002     1894701 :         return;
    1003             :       }
    1004             :     }
    1005     3647779 :     code = ComputeHandler(lookup);
    1006             :   }
    1007             : 
    1008     3929789 :   PatchCache(lookup->name(), code);
    1009     3929791 :   TRACE_IC("LoadIC", lookup->name());
    1010             : }
    1011             : 
    1012     1403844 : StubCache* IC::stub_cache() {
    1013     1403844 :   if (IsAnyLoad()) {
    1014      656535 :     return isolate()->load_stub_cache();
    1015             :   } else {
    1016             :     DCHECK(IsAnyStore());
    1017      747309 :     return isolate()->store_stub_cache();
    1018             :   }
    1019             : }
    1020             : 
    1021     1403715 : void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) {
    1022     1403715 :   stub_cache()->Set(name, map, handler);
    1023     1403715 : }
    1024             : 
    1025        2794 : void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
    1026             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
    1027        5588 :   if (V8_LIKELY(!FLAG_runtime_stats)) return;
    1028           0 :   if (IsAnyLoad()) {
    1029           0 :     TRACE_HANDLER_STATS(isolate(), LoadIC_HandlerCacheHit_Accessor);
    1030             :   } else {
    1031             :     DCHECK(IsAnyStore());
    1032           0 :     TRACE_HANDLER_STATS(isolate(), StoreIC_HandlerCacheHit_Accessor);
    1033             :   }
    1034             : }
    1035             : 
    1036     5401356 : Handle<Object> IC::ComputeHandler(LookupIterator* lookup) {
    1037             :   // Try to find a globally shared handler stub.
    1038     5399201 :   Handle<Object> shared_handler = GetMapIndependentHandler(lookup);
    1039     5399199 :   if (!shared_handler.is_null()) {
    1040             :     DCHECK(IC::IsHandler(*shared_handler));
    1041     5357707 :     return shared_handler;
    1042             :   }
    1043             : 
    1044             :   Handle<Code> handler = PropertyHandlerCompiler::Find(
    1045       41492 :       lookup->name(), receiver_map(), handler_kind());
    1046             :   // Use the cached value if it exists, and if it is different from the
    1047             :   // handler that just missed.
    1048       41492 :   if (!handler.is_null()) {
    1049             :     Handle<Object> current_handler;
    1050        3748 :     if (maybe_handler_.ToHandle(&current_handler)) {
    1051        1593 :       if (!current_handler.is_identical_to(handler)) {
    1052         725 :         TraceHandlerCacheHitStats(lookup);
    1053         725 :         return handler;
    1054             :       }
    1055             :     } else {
    1056             :       // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
    1057             :       // In MEGAMORPHIC case, check if the handler in the megamorphic stub
    1058             :       // cache (which just missed) is different from the cached handler.
    1059        2284 :       if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
    1060             :         Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
    1061             :         Object* megamorphic_cached_handler =
    1062         129 :             stub_cache()->Get(*lookup->name(), map);
    1063         129 :         if (megamorphic_cached_handler != *handler) {
    1064          43 :           TraceHandlerCacheHitStats(lookup);
    1065          43 :           return handler;
    1066             :         }
    1067             :       } else {
    1068        2026 :         TraceHandlerCacheHitStats(lookup);
    1069        2026 :         return handler;
    1070             :       }
    1071             :     }
    1072             :   }
    1073             : 
    1074       38698 :   handler = CompileHandler(lookup);
    1075       38698 :   Map::UpdateCodeCache(receiver_map(), lookup->name(), handler);
    1076       38698 :   return handler;
    1077             : }
    1078             : 
    1079     7224039 : Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
    1080             :   Handle<Object> receiver = lookup->GetReceiver();
    1081     3704524 :   if (receiver->IsString() &&
    1082     3987477 :       *lookup->name() == isolate()->heap()->length_string()) {
    1083       17480 :     FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
    1084       17480 :     return SimpleFieldLoad(isolate(), index);
    1085             :   }
    1086             : 
    1087     3633651 :   if (receiver->IsStringWrapper() &&
    1088        3326 :       *lookup->name() == isolate()->heap()->length_string()) {
    1089         248 :     TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub);
    1090             :     StringLengthStub string_length_stub(isolate());
    1091         248 :     return string_length_stub.GetCode();
    1092             :   }
    1093             : 
    1094             :   // Use specialized code for getting prototype of functions.
    1095     3768075 :   if (receiver->IsJSFunction() &&
    1096      193937 :       *lookup->name() == isolate()->heap()->prototype_string() &&
    1097     3685944 :       receiver->IsConstructor() &&
    1098             :       !Handle<JSFunction>::cast(receiver)
    1099             :            ->map()
    1100             :            ->has_non_instance_prototype()) {
    1101             :     Handle<Code> stub;
    1102       53843 :     TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
    1103       53843 :     return isolate()->builtins()->LoadIC_FunctionPrototype();
    1104             :   }
    1105             : 
    1106     3576234 :   Handle<Map> map = receiver_map();
    1107             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1108             :   bool receiver_is_holder = receiver.is_identical_to(holder);
    1109     3576234 :   switch (lookup->state()) {
    1110             :     case LookupIterator::INTERCEPTOR: {
    1111        1164 :       Handle<Smi> smi_handler = LoadHandler::LoadInterceptor(isolate());
    1112             : 
    1113        2328 :       if (holder->GetNamedInterceptor()->non_masking()) {
    1114             :         Handle<Object> holder_ref = isolate()->factory()->null_value();
    1115         102 :         if (!receiver_is_holder || IsLoadGlobalIC()) {
    1116          28 :           holder_ref = Map::GetOrCreatePrototypeWeakCell(holder, isolate());
    1117             :         }
    1118          65 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNonMaskingInterceptorDH);
    1119          65 :         return LoadFullChain(map, holder_ref, lookup->name(), smi_handler);
    1120             :       }
    1121             : 
    1122        1099 :       if (receiver_is_holder) {
    1123             :         DCHECK(map->has_named_interceptor());
    1124         901 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorDH);
    1125         901 :         return smi_handler;
    1126             :       }
    1127             : 
    1128         198 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptorFromPrototypeDH);
    1129         198 :       return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
    1130             :     }
    1131             : 
    1132             :     case LookupIterator::ACCESSOR: {
    1133             :       // Use simple field loads for some well-known callback properties.
    1134             :       // The method will only return true for absolute truths based on the
    1135             :       // receiver maps.
    1136             :       int object_offset;
    1137      312423 :       if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
    1138             :                                              &object_offset)) {
    1139      373084 :         FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
    1140      186542 :         return SimpleFieldLoad(isolate(), index);
    1141             :       }
    1142             : 
    1143      125881 :       Handle<Object> accessors = lookup->GetAccessors();
    1144      125881 :       if (accessors->IsAccessorPair()) {
    1145      107224 :         if (lookup->TryLookupCachedProperty()) {
    1146             :           DCHECK_EQ(LookupIterator::DATA, lookup->state());
    1147      106584 :           return ComputeHandler(lookup);
    1148             :         }
    1149             : 
    1150             :         // When debugging we need to go the slow path to flood the accessor.
    1151      214396 :         if (GetHostFunction()->shared()->HasDebugInfo()) {
    1152          20 :           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    1153          20 :           return slow_stub();
    1154             :         }
    1155             : 
    1156             :         Handle<Object> getter(AccessorPair::cast(*accessors)->getter(),
    1157             :                               isolate());
    1158      107999 :         if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
    1159         736 :           TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    1160         736 :           return slow_stub();
    1161             :         }
    1162             : 
    1163      106442 :         CallOptimization call_optimization(getter);
    1164      106442 :         if (call_optimization.is_simple_api_call()) {
    1165        1380 :           if (!call_optimization.IsCompatibleReceiverMap(map, holder) ||
    1166         685 :               !holder->HasFastProperties()) {
    1167          29 :             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    1168          29 :             return slow_stub();
    1169             :           }
    1170         666 :           break;
    1171             :         }
    1172             : 
    1173             :         // FunctionTemplate isn't yet supported as smi-handler.
    1174      105747 :         if (getter->IsFunctionTemplateInfo()) {
    1175           0 :           if (!holder->HasFastProperties()) {
    1176           0 :             TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    1177           0 :             return slow_stub();
    1178             :           }
    1179             :           break;
    1180             :         }
    1181             : 
    1182             :         Handle<Smi> smi_handler;
    1183      105747 :         if (holder->HasFastProperties()) {
    1184             :           smi_handler =
    1185      192270 :               LoadHandler::LoadAccessor(isolate(), lookup->GetAccessorIndex());
    1186             : 
    1187       96135 :           if (receiver_is_holder) {
    1188       22682 :             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorDH);
    1189       22682 :             return smi_handler;
    1190             :           }
    1191       73453 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadAccessorFromPrototypeDH);
    1192        9612 :         } else if (holder->IsJSGlobalObject()) {
    1193         956 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
    1194         956 :           smi_handler = LoadHandler::LoadGlobal(isolate());
    1195             :         } else {
    1196        8656 :           smi_handler = LoadHandler::LoadNormal(isolate());
    1197             : 
    1198        8656 :           if (receiver_is_holder) {
    1199        8542 :             TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
    1200        8542 :             return smi_handler;
    1201             :           }
    1202         114 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
    1203             :         }
    1204             : 
    1205       74523 :         return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
    1206             :       }
    1207             : 
    1208             :       Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    1209             : 
    1210       37300 :       if (v8::ToCData<Address>(info->getter()) == nullptr ||
    1211       37272 :           !AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map) ||
    1212       55190 :           !holder->HasFastProperties() ||
    1213         636 :           (info->is_sloppy() && !receiver->IsJSReceiver())) {
    1214         759 :         TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
    1215         759 :         return slow_stub();
    1216             :       }
    1217             : 
    1218             :       Handle<Smi> smi_handler =
    1219       35796 :           LoadHandler::LoadApiGetter(isolate(), lookup->GetAccessorIndex());
    1220       17898 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterDH);
    1221       17898 :       if (receiver_is_holder) return smi_handler;
    1222         610 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterFromPrototypeDH);
    1223         610 :       return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
    1224             :     }
    1225             : 
    1226             :     case LookupIterator::DATA: {
    1227             :       DCHECK_EQ(kData, lookup->property_details().kind());
    1228             :       Handle<Smi> smi_handler;
    1229     3262590 :       if (lookup->is_dictionary_holder()) {
    1230       30565 :         smi_handler = LoadHandler::LoadNormal(isolate());
    1231       30565 :         if (receiver_is_holder) {
    1232             :           DCHECK(!holder->IsJSGlobalObject());
    1233       10814 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
    1234       10814 :           return smi_handler;
    1235             :         }
    1236             : 
    1237       19751 :         if (holder->IsJSGlobalObject()) {
    1238       17942 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
    1239       17942 :           smi_handler = LoadHandler::LoadGlobal(isolate());
    1240             :         } else {
    1241        1809 :           TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
    1242             :         }
    1243             : 
    1244     3232025 :       } else if (lookup->property_details().location() == kField) {
    1245     1851943 :         FieldIndex field = lookup->GetFieldIndex();
    1246     1851944 :         smi_handler = SimpleFieldLoad(isolate(), field);
    1247     1851943 :         if (receiver_is_holder) return smi_handler;
    1248       35292 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldFromPrototypeDH);
    1249             :       } else {
    1250             :         DCHECK_EQ(kDescriptor, lookup->property_details().location());
    1251             :         smi_handler =
    1252     2760164 :             LoadHandler::LoadConstant(isolate(), lookup->GetConstantIndex());
    1253     1380082 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantDH);
    1254     1380082 :         if (receiver_is_holder) return smi_handler;
    1255     1078363 :         TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantFromPrototypeDH);
    1256             :       }
    1257     1133406 :       return LoadFromPrototype(map, holder, lookup->name(), smi_handler);
    1258             :     }
    1259             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
    1260          56 :       TRACE_HANDLER_STATS(isolate(), LoadIC_LoadIntegerIndexedExoticDH);
    1261          56 :       return LoadHandler::LoadNonExistent(isolate());
    1262             :     case LookupIterator::ACCESS_CHECK:
    1263             :     case LookupIterator::JSPROXY:
    1264             :     case LookupIterator::NOT_FOUND:
    1265             :     case LookupIterator::TRANSITION:
    1266           0 :       UNREACHABLE();
    1267             :   }
    1268             : 
    1269         666 :   return Handle<Code>::null();
    1270             : }
    1271             : 
    1272         277 : Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup) {
    1273             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
    1274             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1275         554 :   Handle<Map> map = receiver_map();
    1276             : 
    1277         277 :   Handle<Object> accessors = lookup->GetAccessors();
    1278             :   DCHECK(accessors->IsAccessorPair());
    1279             :   DCHECK(holder->HasFastProperties());
    1280             :   DCHECK(!GetHostFunction()->shared()->HasDebugInfo());
    1281             :   Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
    1282             :                         isolate());
    1283         277 :   CallOptimization call_optimization(getter);
    1284             :   NamedLoadHandlerCompiler compiler(isolate(), map, holder);
    1285             :   DCHECK(call_optimization.is_simple_api_call());
    1286         277 :   TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
    1287         277 :   int index = lookup->GetAccessorIndex();
    1288             :   Handle<Code> code = compiler.CompileLoadCallback(
    1289         277 :       lookup->name(), call_optimization, index, slow_stub());
    1290         554 :   return code;
    1291             : }
    1292             : 
    1293             : 
    1294     1406574 : static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
    1295             :   // This helper implements a few common fast cases for converting
    1296             :   // non-smi keys of keyed loads/stores to a smi or a string.
    1297     1406574 :   if (key->IsHeapNumber()) {
    1298             :     double value = Handle<HeapNumber>::cast(key)->value();
    1299        3045 :     if (std::isnan(value)) {
    1300             :       key = isolate->factory()->nan_string();
    1301             :     } else {
    1302             :       int int_value = FastD2I(value);
    1303        2731 :       if (value == int_value && Smi::IsValid(int_value)) {
    1304             :         key = handle(Smi::FromInt(int_value), isolate);
    1305             :       }
    1306             :     }
    1307     1403529 :   } else if (key->IsUndefined(isolate)) {
    1308             :     key = isolate->factory()->undefined_string();
    1309     1395707 :   } else if (key->IsString()) {
    1310      467576 :     key = isolate->factory()->InternalizeString(Handle<String>::cast(key));
    1311             :   }
    1312     1406574 :   return key;
    1313             : }
    1314             : 
    1315      413610 : void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
    1316      446639 :   Handle<Map> receiver_map(receiver->map(), isolate());
    1317             :   DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
    1318             :          receiver_map->instance_type() != JS_PROXY_TYPE);  // Checked by caller.
    1319             :   MapHandleList target_receiver_maps;
    1320      413610 :   TargetMaps(&target_receiver_maps);
    1321             : 
    1322      413610 :   if (target_receiver_maps.length() == 0) {
    1323      380551 :     Handle<Object> handler = LoadElementHandler(receiver_map);
    1324      380551 :     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
    1325             :   }
    1326             : 
    1327       52925 :   for (int i = 0; i < target_receiver_maps.length(); i++) {
    1328       52955 :     Handle<Map> map = target_receiver_maps.at(i);
    1329       52955 :     if (map.is_null()) continue;
    1330       52955 :     if (map->instance_type() == JS_VALUE_TYPE) {
    1331             :       TRACE_GENERIC_IC("JSValue");
    1332             :       return;
    1333             :     }
    1334       52940 :     if (map->instance_type() == JS_PROXY_TYPE) {
    1335             :       TRACE_GENERIC_IC("JSProxy");
    1336             :       return;
    1337             :     }
    1338             :   }
    1339             : 
    1340             :   // The first time a receiver is seen that is a transitioned version of the
    1341             :   // previous monomorphic receiver type, assume the new ElementsKind is the
    1342             :   // monomorphic type. This benefits global arrays that only transition
    1343             :   // once, and all call sites accessing them are faster if they remain
    1344             :   // monomorphic. If this optimistic assumption is not true, the IC will
    1345             :   // miss again and it will become polymorphic and support both the
    1346             :   // untransitioned and transitioned maps.
    1347       77433 :   if (state() == MONOMORPHIC && !receiver->IsString() &&
    1348             :       IsMoreGeneralElementsKindTransition(
    1349             :           target_receiver_maps.at(0)->elements_kind(),
    1350       22026 :           Handle<JSObject>::cast(receiver)->GetElementsKind())) {
    1351        4470 :     Handle<Object> handler = LoadElementHandler(receiver_map);
    1352        4470 :     return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
    1353             :   }
    1354             : 
    1355             :   DCHECK(state() != GENERIC);
    1356             : 
    1357             :   // Determine the list of receiver maps that this call site has seen,
    1358             :   // adding the map that was just encountered.
    1359       28559 :   if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
    1360             :     // If the miss wasn't due to an unseen map, a polymorphic stub
    1361             :     // won't help, use the generic stub.
    1362             :     TRACE_GENERIC_IC("same map added twice");
    1363             :     return;
    1364             :   }
    1365             : 
    1366             :   // If the maximum number of receiver maps has been exceeded, use the generic
    1367             :   // version of the IC.
    1368       21831 :   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
    1369             :     TRACE_GENERIC_IC("max polymorph exceeded");
    1370             :     return;
    1371             :   }
    1372             : 
    1373             :   List<Handle<Object>> handlers(target_receiver_maps.length());
    1374       18932 :   LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers);
    1375       18932 :   ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
    1376             : }
    1377             : 
    1378      433064 : Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map) {
    1379      433189 :   if (receiver_map->has_indexed_interceptor() &&
    1380             :       !receiver_map->GetIndexedInterceptor()->getter()->IsUndefined(
    1381      998363 :           isolate()) &&
    1382             :       !receiver_map->GetIndexedInterceptor()->non_masking()) {
    1383          97 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedInterceptorStub);
    1384          97 :     return LoadIndexedInterceptorStub(isolate()).GetCode();
    1385             :   }
    1386      432967 :   if (receiver_map->IsStringMap()) {
    1387        1709 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadIndexedStringStub);
    1388        1709 :     return isolate()->builtins()->KeyedLoadIC_IndexedString();
    1389             :   }
    1390             :   InstanceType instance_type = receiver_map->instance_type();
    1391      431258 :   if (instance_type < FIRST_JS_RECEIVER_TYPE) {
    1392          45 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_SlowStub);
    1393          45 :     return isolate()->builtins()->KeyedLoadIC_Slow();
    1394             :   }
    1395             : 
    1396             :   ElementsKind elements_kind = receiver_map->elements_kind();
    1397      431213 :   if (IsSloppyArgumentsElementsKind(elements_kind)) {
    1398        3189 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
    1399        3189 :     return KeyedLoadSloppyArgumentsStub(isolate()).GetCode();
    1400             :   }
    1401      428024 :   bool is_js_array = instance_type == JS_ARRAY_TYPE;
    1402      428024 :   if (elements_kind == DICTIONARY_ELEMENTS) {
    1403       10529 :     TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
    1404             :     return LoadHandler::LoadElement(isolate(), elements_kind, false,
    1405       21058 :                                     is_js_array);
    1406             :   }
    1407             :   DCHECK(IsFastElementsKind(elements_kind) ||
    1408             :          IsFixedTypedArrayElementsKind(elements_kind));
    1409             :   // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind).
    1410             :   bool convert_hole_to_undefined =
    1411      549633 :       is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
    1412      132138 :       *receiver_map == isolate()->get_initial_js_array_map(elements_kind);
    1413      417495 :   TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_LoadElementDH);
    1414             :   return LoadHandler::LoadElement(isolate(), elements_kind,
    1415      834990 :                                   convert_hole_to_undefined, is_js_array);
    1416             : }
    1417             : 
    1418       18932 : void KeyedLoadIC::LoadElementPolymorphicHandlers(
    1419       66975 :     MapHandleList* receiver_maps, List<Handle<Object>>* handlers) {
    1420      133950 :   for (int i = 0; i < receiver_maps->length(); ++i) {
    1421       48043 :     Handle<Map> receiver_map(receiver_maps->at(i));
    1422             : 
    1423             :     // Mark all stable receiver maps that have elements kind transition map
    1424             :     // among receiver_maps as unstable because the optimizing compilers may
    1425             :     // generate an elements kind transition for this kind of receivers.
    1426       48043 :     if (receiver_map->is_stable()) {
    1427       30630 :       Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps);
    1428       30630 :       if (tmap != nullptr) {
    1429          30 :         receiver_map->NotifyLeafMapLayoutChange();
    1430             :       }
    1431             :     }
    1432       48043 :     handlers->Add(LoadElementHandler(receiver_map));
    1433             :   }
    1434       18932 : }
    1435             : 
    1436      704068 : MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
    1437             :                                       Handle<Object> key) {
    1438      704068 :   if (MigrateDeprecated(object)) {
    1439             :     Handle<Object> result;
    1440     2245468 :     ASSIGN_RETURN_ON_EXCEPTION(
    1441             :         isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
    1442             :         Object);
    1443             :     return result;
    1444             :   }
    1445             : 
    1446             :   Handle<Object> load_handle;
    1447             : 
    1448             :   // Check for non-string values that can be converted into an
    1449             :   // internalized string directly or is representable as a smi.
    1450      704036 :   key = TryConvertKey(key, isolate());
    1451             : 
    1452             :   uint32_t index;
    1453      941786 :   if ((key->IsInternalizedString() &&
    1454     1415318 :        !String::cast(*key)->AsArrayIndex(&index)) ||
    1455             :       key->IsSymbol()) {
    1456      560010 :     ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
    1457             :                                LoadIC::Load(object, Handle<Name>::cast(key)),
    1458             :                                Object);
    1459     1271953 :   } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
    1460             :              !object->IsJSValue()) {
    1461     1276804 :     if ((object->IsJSObject() && key->IsSmi()) ||
    1462        1918 :         (object->IsString() && key->IsNumber())) {
    1463      413610 :       UpdateLoadElement(Handle<HeapObject>::cast(object));
    1464      413610 :       if (is_vector_set()) {
    1465      403953 :         TRACE_IC("LoadIC", key);
    1466             :       }
    1467             :     }
    1468             :   }
    1469             : 
    1470      703727 :   if (!is_vector_set()) {
    1471       20078 :     ConfigureVectorState(MEGAMORPHIC, key);
    1472       20078 :     TRACE_IC("LoadIC", key);
    1473             :   }
    1474             : 
    1475      703727 :   if (!load_handle.is_null()) return load_handle;
    1476             : 
    1477             :   Handle<Object> result;
    1478      848062 :   ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    1479             :                              Runtime::GetObjectProperty(isolate(), object, key),
    1480             :                              Object);
    1481             :   return result;
    1482             : }
    1483             : 
    1484             : 
    1485     3876445 : bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
    1486             :                              JSReceiver::StoreFromKeyed store_mode) {
    1487             :   // Disable ICs for non-JSObjects for now.
    1488             :   Handle<Object> object = it->GetReceiver();
    1489     1935965 :   if (!object->IsJSObject()) return false;
    1490             :   Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    1491             :   DCHECK(!receiver->map()->is_deprecated());
    1492             : 
    1493     1943492 :   for (; it->IsFound(); it->Next()) {
    1494      641405 :     switch (it->state()) {
    1495             :       case LookupIterator::NOT_FOUND:
    1496             :       case LookupIterator::TRANSITION:
    1497           0 :         UNREACHABLE();
    1498             :       case LookupIterator::JSPROXY:
    1499             :         return false;
    1500             :       case LookupIterator::INTERCEPTOR: {
    1501             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
    1502         195 :         InterceptorInfo* info = holder->GetNamedInterceptor();
    1503         195 :         if (it->HolderIsReceiverOrHiddenPrototype()) {
    1504         522 :           return !info->non_masking() && receiver.is_identical_to(holder) &&
    1505         174 :                  !info->setter()->IsUndefined(it->isolate());
    1506          21 :         } else if (!info->getter()->IsUndefined(it->isolate()) ||
    1507             :                    !info->query()->IsUndefined(it->isolate())) {
    1508             :           return false;
    1509             :         }
    1510             :         break;
    1511             :       }
    1512             :       case LookupIterator::ACCESS_CHECK:
    1513        4071 :         if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
    1514             :         break;
    1515             :       case LookupIterator::ACCESSOR:
    1516       58716 :         return !it->IsReadOnly();
    1517             :       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    1518             :         return false;
    1519             :       case LookupIterator::DATA: {
    1520      578157 :         if (it->IsReadOnly()) return false;
    1521             :         Handle<JSObject> holder = it->GetHolder<JSObject>();
    1522      555047 :         if (receiver.is_identical_to(holder)) {
    1523      409478 :           it->PrepareForDataProperty(value);
    1524             :           // The previous receiver map might just have been deprecated,
    1525             :           // so reload it.
    1526      409478 :           update_receiver_map(receiver);
    1527      409478 :           return true;
    1528             :         }
    1529             : 
    1530             :         // Receiver != holder.
    1531      145569 :         if (receiver->IsJSGlobalProxy()) {
    1532         846 :           PrototypeIterator iter(it->isolate(), receiver);
    1533             :           return it->GetHolder<Object>().is_identical_to(
    1534             :               PrototypeIterator::GetCurrent(iter));
    1535             :         }
    1536             : 
    1537      144723 :         if (it->HolderIsReceiverOrHiddenPrototype()) return false;
    1538             : 
    1539      144723 :         if (it->ExtendingNonExtensible(receiver)) return false;
    1540      144723 :         it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
    1541      144723 :         return it->IsCacheableTransition();
    1542             :       }
    1543             :     }
    1544             :   }
    1545             : 
    1546     1298034 :   receiver = it->GetStoreTarget();
    1547     1298034 :   if (it->ExtendingNonExtensible(receiver)) return false;
    1548     1297917 :   it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
    1549     1297917 :   return it->IsCacheableTransition();
    1550             : }
    1551             : 
    1552     1690942 : MaybeHandle<Object> StoreGlobalIC::Store(Handle<Object> object,
    1553             :                                          Handle<Name> name,
    1554             :                                          Handle<Object> value) {
    1555             :   DCHECK(object->IsJSGlobalObject());
    1556             :   DCHECK(name->IsString());
    1557             : 
    1558             :   // Look up in script context table.
    1559     1690942 :   Handle<String> str_name = Handle<String>::cast(name);
    1560             :   Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
    1561             :   Handle<ScriptContextTable> script_contexts(
    1562             :       global->native_context()->script_context_table());
    1563             : 
    1564             :   ScriptContextTable::LookupResult lookup_result;
    1565     1690942 :   if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
    1566             :     Handle<Context> script_context = ScriptContextTable::GetContext(
    1567          82 :         script_contexts, lookup_result.context_index);
    1568          82 :     if (lookup_result.mode == CONST) {
    1569         122 :       return TypeError(MessageTemplate::kConstAssign, object, name);
    1570             :     }
    1571             : 
    1572             :     Handle<Object> previous_value =
    1573         116 :         FixedArray::get(*script_context, lookup_result.slot_index, isolate());
    1574             : 
    1575          58 :     if (previous_value->IsTheHole(isolate())) {
    1576             :       // Do not install stubs and stay pre-monomorphic for
    1577             :       // uninitialized accesses.
    1578          18 :       return ReferenceError(name);
    1579             :     }
    1580             : 
    1581          80 :     if (FLAG_use_ic && StoreScriptContextFieldStub::Accepted(&lookup_result)) {
    1582          40 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
    1583             :       StoreScriptContextFieldStub stub(isolate(), &lookup_result);
    1584          80 :       PatchCache(name, stub.GetCode());
    1585             :     }
    1586             : 
    1587          80 :     script_context->set(lookup_result.slot_index, *value);
    1588             :     return value;
    1589             :   }
    1590             : 
    1591     1690860 :   return StoreIC::Store(object, name, value);
    1592             : }
    1593             : 
    1594     6180193 : MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
    1595             :                                    Handle<Object> value,
    1596             :                                    JSReceiver::StoreFromKeyed store_mode) {
    1597             :   // TODO(verwaest): Let SetProperty do the migration, since storing a property
    1598             :   // might deprecate the current map again, if value does not fit.
    1599    12359722 :   if (MigrateDeprecated(object) || object->IsJSProxy()) {
    1600             :     Handle<Object> result;
    1601        4634 :     ASSIGN_RETURN_ON_EXCEPTION(
    1602             :         isolate(), result,
    1603             :         Object::SetProperty(object, name, value, language_mode()), Object);
    1604             :     return result;
    1605             :   }
    1606             : 
    1607             :   // If the object is undefined or null it's illegal to try to set any
    1608             :   // properties on it; throw a TypeError in that case.
    1609    20469593 :   if (object->IsNullOrUndefined(isolate())) {
    1610         100 :     if (FLAG_use_ic && state() != UNINITIALIZED && state() != PREMONOMORPHIC) {
    1611             :       // Ensure the IC state progresses.
    1612          15 :       TRACE_HANDLER_STATS(isolate(), StoreIC_NonReceiver);
    1613          15 :       update_receiver_map(object);
    1614          15 :       PatchCache(name, slow_stub());
    1615          15 :       TRACE_IC("StoreIC", name);
    1616             :     }
    1617          50 :     return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
    1618             :   }
    1619             : 
    1620     6177826 :   if (state() != UNINITIALIZED) {
    1621     1935965 :     JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
    1622             :   }
    1623     6177826 :   LookupIterator it(object, name);
    1624     6177828 :   if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
    1625             : 
    1626     6177828 :   MAYBE_RETURN_NULL(
    1627             :       Object::SetProperty(&it, value, language_mode(), store_mode));
    1628             :   return value;
    1629             : }
    1630             : 
    1631     6177368 : void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
    1632             :                            JSReceiver::StoreFromKeyed store_mode) {
    1633     6177368 :   if (state() == UNINITIALIZED) {
    1634             :     // This is the first time we execute this inline cache. Set the target to
    1635             :     // the pre monomorphic stub to delay setting the monomorphic state.
    1636     4241403 :     TRACE_HANDLER_STATS(isolate(), StoreIC_Premonomorphic);
    1637     4241403 :     ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
    1638     4241403 :     TRACE_IC("StoreIC", lookup->name());
    1639    10418771 :     return;
    1640             :   }
    1641             : 
    1642             :   Handle<Object> handler;
    1643     1935965 :   if (LookupForWrite(lookup, value, store_mode)) {
    1644     1751396 :     handler = ComputeHandler(lookup);
    1645             :   } else {
    1646             :     TRACE_GENERIC_IC("LookupForWrite said 'false'");
    1647      184569 :     handler = slow_stub();
    1648             :   }
    1649             : 
    1650     1935965 :   PatchCache(lookup->name(), handler);
    1651     1935965 :   TRACE_IC("StoreIC", lookup->name());
    1652             : }
    1653             : 
    1654     1279632 : Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
    1655             :                                         Handle<JSObject> holder,
    1656             :                                         Handle<Map> transition,
    1657             :                                         Handle<Name> name) {
    1658             :   Handle<Object> smi_handler;
    1659     1279632 :   if (transition->is_dictionary_map()) {
    1660     5316304 :     smi_handler = StoreHandler::StoreNormal(isolate());
    1661             :   } else {
    1662             :     int descriptor = transition->LastAdded();
    1663             :     Handle<DescriptorArray> descriptors(transition->instance_descriptors());
    1664     1261566 :     PropertyDetails details = descriptors->GetDetails(descriptor);
    1665             :     Representation representation = details.representation();
    1666             :     DCHECK(!representation.IsNone());
    1667             : 
    1668             :     // Declarative handlers don't support access checks.
    1669             :     DCHECK(!transition->is_access_check_needed());
    1670             : 
    1671             :     DCHECK_EQ(kData, details.kind());
    1672     1261566 :     if (details.location() == kDescriptor) {
    1673       75212 :       smi_handler = StoreHandler::TransitionToConstant(isolate(), descriptor);
    1674             : 
    1675             :     } else {
    1676             :       DCHECK_EQ(kField, details.location());
    1677             :       bool extend_storage =
    1678     1186354 :           Map::cast(transition->GetBackPointer())->unused_property_fields() ==
    1679     1186354 :           0;
    1680             : 
    1681     1186354 :       FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor);
    1682             :       smi_handler = StoreHandler::TransitionToField(
    1683             :           isolate(), descriptor, index, representation, extend_storage);
    1684             :     }
    1685             :   }
    1686             :   // |holder| is either a receiver if the property is non-existent or
    1687             :   // one of the prototypes.
    1688             :   DCHECK(!holder.is_null());
    1689     1279632 :   bool is_nonexistent = holder->map() == transition->GetBackPointer();
    1690     1279632 :   if (is_nonexistent) holder = Handle<JSObject>::null();
    1691             : 
    1692             :   int checks_count =
    1693             :       GetPrototypeCheckCount(isolate(), receiver_map, holder, name);
    1694             :   DCHECK_LE(0, checks_count);
    1695             :   DCHECK(!receiver_map->IsJSGlobalObjectMap());
    1696             : 
    1697             :   Handle<Object> validity_cell =
    1698     1279632 :       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
    1699     1279632 :   if (validity_cell.is_null()) {
    1700             :     DCHECK_EQ(0, checks_count);
    1701             :     validity_cell = handle(Smi::kZero, isolate());
    1702             :   }
    1703             : 
    1704     1279632 :   Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition);
    1705             : 
    1706             :   Factory* factory = isolate()->factory();
    1707     1279632 :   if (checks_count == 0) {
    1708     1279002 :     return factory->NewTuple3(transition_cell, smi_handler, validity_cell);
    1709             :   }
    1710             :   Handle<FixedArray> handler_array(factory->NewFixedArray(
    1711         630 :       StoreHandler::kFirstPrototypeIndex + checks_count, TENURED));
    1712         630 :   handler_array->set(StoreHandler::kSmiHandlerIndex, *smi_handler);
    1713         630 :   handler_array->set(StoreHandler::kValidityCellIndex, *validity_cell);
    1714         630 :   handler_array->set(StoreHandler::kTransitionCellIndex, *transition_cell);
    1715             :   InitPrototypeChecks(isolate(), receiver_map, holder, name, handler_array,
    1716         630 :                       StoreHandler::kFirstPrototypeIndex);
    1717         630 :   return handler_array;
    1718             : }
    1719             : 
    1720             : namespace {
    1721             : 
    1722             : Handle<Object> StoreGlobal(Isolate* isolate, Handle<PropertyCell> cell) {
    1723       77644 :   return isolate->factory()->NewWeakCell(cell);
    1724             : }
    1725             : 
    1726             : }  // namespace
    1727             : 
    1728     1751396 : Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
    1729             :   DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
    1730             : 
    1731             :   // This is currently guaranteed by checks in StoreIC::Store.
    1732             :   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
    1733             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1734             :   DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
    1735             : 
    1736     1751396 :   switch (lookup->state()) {
    1737             :     case LookupIterator::TRANSITION: {
    1738     1282736 :       auto store_target = lookup->GetStoreTarget();
    1739     1282736 :       if (store_target->IsJSGlobalObject()) {
    1740      470773 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH);
    1741             :         return StoreGlobal(isolate(), lookup->transition_cell());
    1742             :       }
    1743             :       // Currently not handled by CompileStoreTransition.
    1744     1280014 :       if (!holder->HasFastProperties()) {
    1745             :         TRACE_GENERIC_IC("transition from slow");
    1746         382 :         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1747         382 :         return slow_stub();
    1748             :       }
    1749             : 
    1750             :       DCHECK(lookup->IsCacheableTransition());
    1751     1279632 :       Handle<Map> transition = lookup->transition_map();
    1752     1279632 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransitionDH);
    1753             :       return StoreTransition(receiver_map(), holder, transition,
    1754     1279632 :                              lookup->name());
    1755             :     }
    1756             : 
    1757             :     case LookupIterator::INTERCEPTOR: {
    1758             :       DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
    1759         153 :       TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
    1760             :       StoreInterceptorStub stub(isolate());
    1761         153 :       return stub.GetCode();
    1762             :     }
    1763             : 
    1764             :     case LookupIterator::ACCESSOR: {
    1765       58213 :       if (!holder->HasFastProperties()) {
    1766             :         TRACE_GENERIC_IC("accessor on slow map");
    1767         410 :         TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1768         410 :         return slow_stub();
    1769             :       }
    1770       57803 :       Handle<Object> accessors = lookup->GetAccessors();
    1771       57803 :       if (accessors->IsAccessorInfo()) {
    1772             :         Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    1773       21309 :         if (v8::ToCData<Address>(info->setter()) == nullptr) {
    1774             :           TRACE_GENERIC_IC("setter == nullptr");
    1775           7 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1776           7 :           return slow_stub();
    1777             :         }
    1778       42467 :         if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
    1779       21165 :             !lookup->HolderIsReceiverOrHiddenPrototype()) {
    1780             :           TRACE_GENERIC_IC("special data property in prototype chain");
    1781         135 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1782         135 :           return slow_stub();
    1783             :         }
    1784       21167 :         if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
    1785       21167 :                                                    receiver_map())) {
    1786             :           TRACE_GENERIC_IC("incompatible receiver type");
    1787          14 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1788          14 :           return slow_stub();
    1789             :         }
    1790             :         break;  // Custom-compiled handler.
    1791       36494 :       } else if (accessors->IsAccessorPair()) {
    1792             :         Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
    1793             :                               isolate());
    1794       53378 :         if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
    1795             :           TRACE_GENERIC_IC("setter not a function");
    1796       16818 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1797       16818 :           return slow_stub();
    1798             :         }
    1799       19676 :         CallOptimization call_optimization(setter);
    1800       19676 :         if (call_optimization.is_simple_api_call()) {
    1801         117 :           if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
    1802             :             break;  // Custom-compiled handler.
    1803             :           }
    1804             :           TRACE_GENERIC_IC("incompatible receiver");
    1805           3 :           TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1806           3 :           return slow_stub();
    1807             :         }
    1808             :         break;  // Custom-compiled handler.
    1809             :       }
    1810           0 :       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1811           0 :       return slow_stub();
    1812             :     }
    1813             : 
    1814             :     case LookupIterator::DATA: {
    1815             :       DCHECK_EQ(kData, lookup->property_details().kind());
    1816      410294 :       if (lookup->is_dictionary_holder()) {
    1817       80911 :         if (holder->IsJSGlobalObject()) {
    1818       74922 :           TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
    1819       74922 :           return StoreGlobal(isolate(), lookup->GetPropertyCell());
    1820             :         }
    1821        5989 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
    1822             :         DCHECK(holder.is_identical_to(receiver));
    1823        5989 :         return StoreHandler::StoreNormal(isolate());
    1824             :       }
    1825             : 
    1826             :       // -------------- Fields --------------
    1827      329383 :       if (lookup->property_details().location() == kField) {
    1828      329326 :         TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH);
    1829      329326 :         int descriptor = lookup->GetFieldDescriptorIndex();
    1830      329326 :         FieldIndex index = lookup->GetFieldIndex();
    1831             :         PropertyConstness constness = lookup->constness();
    1832      329326 :         if (constness == kConst && IsStoreOwnICKind(nexus()->kind())) {
    1833             :           // StoreOwnICs are used for initializing object literals therefore
    1834             :           // we must store the value unconditionally even to kConst fields.
    1835             :           constness = kMutable;
    1836             :         }
    1837             :         return StoreHandler::StoreField(isolate(), descriptor, index, constness,
    1838      329326 :                                         lookup->representation());
    1839             :       }
    1840             : 
    1841             :       // -------------- Constant properties --------------
    1842             :       DCHECK_EQ(kDescriptor, lookup->property_details().location());
    1843             :       TRACE_GENERIC_IC("constant property");
    1844          57 :       TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
    1845          57 :       return slow_stub();
    1846             :     }
    1847             : 
    1848             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
    1849             :     case LookupIterator::ACCESS_CHECK:
    1850             :     case LookupIterator::JSPROXY:
    1851             :     case LookupIterator::NOT_FOUND:
    1852           0 :       UNREACHABLE();
    1853             :   }
    1854       40826 :   return Handle<Code>::null();
    1855             : }
    1856             : 
    1857       38421 : Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup) {
    1858             :   DCHECK_EQ(LookupIterator::ACCESSOR, lookup->state());
    1859             : 
    1860             :   // This is currently guaranteed by checks in StoreIC::Store.
    1861       38421 :   Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
    1862             :   Handle<JSObject> holder = lookup->GetHolder<JSObject>();
    1863             :   DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
    1864             : 
    1865             :   DCHECK(holder->HasFastProperties());
    1866       38421 :   Handle<Object> accessors = lookup->GetAccessors();
    1867             : 
    1868       38421 :   if (accessors->IsAccessorInfo()) {
    1869       20287 :     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
    1870             :     DCHECK(v8::ToCData<Address>(info->setter()) != 0);
    1871             :     DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
    1872             :            lookup->HolderIsReceiverOrHiddenPrototype());
    1873             :     DCHECK(
    1874             :         AccessorInfo::IsCompatibleReceiverMap(isolate(), info, receiver_map()));
    1875       56555 :     TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
    1876             :     NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
    1877             :     // TODO(ishell): don't hard-code language mode into the handler because
    1878             :     // this handler can be re-used through megamorphic stub cache for wrong
    1879             :     // language mode.
    1880             :     // Better pass vector/slot to Runtime::kStoreCallbackProperty and
    1881             :     // let it decode the language mode from the IC kind.
    1882             :     Handle<Code> code = compiler.CompileStoreCallback(receiver, lookup->name(),
    1883       20287 :                                                       info, language_mode());
    1884       20287 :     return code;
    1885             :   }
    1886             : 
    1887             :   DCHECK(accessors->IsAccessorPair());
    1888             :   Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
    1889             :                         isolate());
    1890             :   DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
    1891       18134 :   CallOptimization call_optimization(setter);
    1892             :   NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
    1893       18134 :   if (call_optimization.is_simple_api_call()) {
    1894             :     DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
    1895          70 :     TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
    1896             :     Handle<Code> code = compiler.CompileStoreCallback(
    1897             :         receiver, lookup->name(), call_optimization, lookup->GetAccessorIndex(),
    1898          70 :         slow_stub());
    1899          70 :     return code;
    1900             :   }
    1901       18064 :   TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
    1902             :   int expected_arguments =
    1903             :       JSFunction::cast(*setter)->shared()->internal_formal_parameter_count();
    1904             :   return compiler.CompileStoreViaSetter(
    1905       18064 :       receiver, lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
    1906             : }
    1907             : 
    1908      247830 : void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
    1909             :                                       KeyedAccessStoreMode store_mode) {
    1910             :   MapHandleList target_receiver_maps;
    1911      280263 :   TargetMaps(&target_receiver_maps);
    1912      247830 :   if (target_receiver_maps.length() == 0) {
    1913             :     Handle<Map> monomorphic_map =
    1914      215367 :         ComputeTransitionedMap(receiver_map, store_mode);
    1915             :     store_mode = GetNonTransitioningStoreMode(store_mode);
    1916      215367 :     Handle<Object> handler = StoreElementHandler(monomorphic_map, store_mode);
    1917      215367 :     return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
    1918             :   }
    1919             : 
    1920       41336 :   for (int i = 0; i < target_receiver_maps.length(); i++) {
    1921       82732 :     if (!target_receiver_maps.at(i).is_null() &&
    1922             :         target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
    1923             :       TRACE_GENERIC_IC("JSValue");
    1924             :       return;
    1925             :     }
    1926             :   }
    1927             : 
    1928             :   // There are several special cases where an IC that is MONOMORPHIC can still
    1929             :   // transition to a different GetNonTransitioningStoreMode IC that handles a
    1930             :   // superset of the original IC. Handle those here if the receiver map hasn't
    1931             :   // changed or it has transitioned to a more general kind.
    1932             :   KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
    1933       32433 :   Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
    1934       32433 :   if (state() == MONOMORPHIC) {
    1935             :     Handle<Map> transitioned_receiver_map = receiver_map;
    1936       27526 :     if (IsTransitionStoreMode(store_mode)) {
    1937             :       transitioned_receiver_map =
    1938       15433 :           ComputeTransitionedMap(receiver_map, store_mode);
    1939             :     }
    1940       37938 :     if ((receiver_map.is_identical_to(previous_receiver_map) &&
    1941       46547 :          IsTransitionStoreMode(store_mode)) ||
    1942             :         IsTransitionOfMonomorphicTarget(*previous_receiver_map,
    1943       19021 :                                         *transitioned_receiver_map)) {
    1944             :       // If the "old" and "new" maps are in the same elements map family, or
    1945             :       // if they at least come from the same origin for a transitioning store,
    1946             :       // stay MONOMORPHIC and use the map for the most generic ElementsKind.
    1947             :       store_mode = GetNonTransitioningStoreMode(store_mode);
    1948             :       Handle<Object> handler =
    1949       13570 :           StoreElementHandler(transitioned_receiver_map, store_mode);
    1950       13570 :       ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
    1951             :       return;
    1952             :     }
    1953       15863 :     if (receiver_map.is_identical_to(previous_receiver_map) &&
    1954       15531 :         old_store_mode == STANDARD_STORE &&
    1955        3150 :         (store_mode == STORE_AND_GROW_NO_TRANSITION ||
    1956        2932 :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    1957             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
    1958             :       // A "normal" IC that handles stores can switch to a version that can
    1959             :       // grow at the end of the array, handle OOB accesses or copy COW arrays
    1960             :       // and still stay MONOMORPHIC.
    1961         253 :       Handle<Object> handler = StoreElementHandler(receiver_map, store_mode);
    1962         253 :       return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
    1963             :     }
    1964             :   }
    1965             : 
    1966             :   DCHECK(state() != GENERIC);
    1967             : 
    1968             :   bool map_added =
    1969       18610 :       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
    1970             : 
    1971       18610 :   if (IsTransitionStoreMode(store_mode)) {
    1972             :     Handle<Map> transitioned_receiver_map =
    1973        7133 :         ComputeTransitionedMap(receiver_map, store_mode);
    1974             :     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
    1975        7133 :                                             transitioned_receiver_map);
    1976             :   }
    1977             : 
    1978       18610 :   if (!map_added) {
    1979             :     // If the miss wasn't due to an unseen map, a polymorphic stub
    1980             :     // won't help, use the megamorphic stub which can handle everything.
    1981             :     TRACE_GENERIC_IC("same map added twice");
    1982             :     return;
    1983             :   }
    1984             : 
    1985             :   // If the maximum number of receiver maps has been exceeded, use the
    1986             :   // megamorphic version of the IC.
    1987       16496 :   if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return;
    1988             : 
    1989             :   // Make sure all polymorphic handlers have the same store mode, otherwise the
    1990             :   // megamorphic stub must be used.
    1991             :   store_mode = GetNonTransitioningStoreMode(store_mode);
    1992       15227 :   if (old_store_mode != STANDARD_STORE) {
    1993        3420 :     if (store_mode == STANDARD_STORE) {
    1994             :       store_mode = old_store_mode;
    1995        3138 :     } else if (store_mode != old_store_mode) {
    1996             :       TRACE_GENERIC_IC("store mode mismatch");
    1997             :       return;
    1998             :     }
    1999             :   }
    2000             : 
    2001             :   // If the store mode isn't the standard mode, make sure that all polymorphic
    2002             :   // receivers are either external arrays, or all "normal" arrays. Otherwise,
    2003             :   // use the megamorphic stub.
    2004       15227 :   if (store_mode != STANDARD_STORE) {
    2005             :     int external_arrays = 0;
    2006        7880 :     for (int i = 0; i < target_receiver_maps.length(); ++i) {
    2007       15760 :       if (target_receiver_maps[i]->has_fixed_typed_array_elements()) {
    2008          45 :         external_arrays++;
    2009             :       }
    2010             :     }
    2011        3752 :     if (external_arrays != 0 &&
    2012             :         external_arrays != target_receiver_maps.length()) {
    2013             :       TRACE_GENERIC_IC("unsupported combination of external and normal arrays");
    2014             :       return;
    2015             :     }
    2016             :   }
    2017             : 
    2018             :   List<Handle<Object>> handlers(target_receiver_maps.length());
    2019       15182 :   StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
    2020       15182 :   ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
    2021             : }
    2022             : 
    2023             : 
    2024      237933 : Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
    2025             :     Handle<Map> map, KeyedAccessStoreMode store_mode) {
    2026      237933 :   switch (store_mode) {
    2027             :     case STORE_TRANSITION_TO_OBJECT:
    2028             :     case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
    2029             :       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
    2030             :                               ? FAST_HOLEY_ELEMENTS
    2031       72528 :                               : FAST_ELEMENTS;
    2032       72528 :       return Map::TransitionElementsTo(map, kind);
    2033             :     }
    2034             :     case STORE_TRANSITION_TO_DOUBLE:
    2035             :     case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
    2036             :       ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
    2037             :                               ? FAST_HOLEY_DOUBLE_ELEMENTS
    2038        4948 :                               : FAST_DOUBLE_ELEMENTS;
    2039        4948 :       return Map::TransitionElementsTo(map, kind);
    2040             :     }
    2041             :     case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
    2042             :       DCHECK(map->has_fixed_typed_array_elements());
    2043             :     // Fall through
    2044             :     case STORE_NO_TRANSITION_HANDLE_COW:
    2045             :     case STANDARD_STORE:
    2046             :     case STORE_AND_GROW_NO_TRANSITION:
    2047      160457 :       return map;
    2048             :   }
    2049           0 :   UNREACHABLE();
    2050             :   return MaybeHandle<Map>().ToHandleChecked();
    2051             : }
    2052             : 
    2053      256173 : Handle<Object> KeyedStoreIC::StoreElementHandler(
    2054             :     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
    2055             :   DCHECK(store_mode == STANDARD_STORE ||
    2056             :          store_mode == STORE_AND_GROW_NO_TRANSITION ||
    2057             :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    2058             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
    2059             :   DCHECK(!receiver_map->DictionaryElementsInPrototypeChainOnly());
    2060             : 
    2061             :   ElementsKind elements_kind = receiver_map->elements_kind();
    2062      256173 :   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
    2063             :   Handle<Code> stub;
    2064      256173 :   if (receiver_map->has_sloppy_arguments_elements()) {
    2065      762154 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
    2066           0 :     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
    2067      292272 :   } else if (receiver_map->has_fast_elements() ||
    2068             :              receiver_map->has_fixed_typed_array_elements()) {
    2069      253466 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
    2070             :     stub =
    2071             :         StoreFastElementStub(isolate(), is_jsarray, elements_kind, store_mode)
    2072      506932 :             .GetCode();
    2073             :   } else {
    2074        2707 :     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
    2075             :     DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
    2076        5414 :     stub = StoreSlowElementStub(isolate(), store_mode).GetCode();
    2077             :   }
    2078             :   Handle<Object> validity_cell =
    2079      256173 :       Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
    2080      256173 :   if (validity_cell.is_null()) return stub;
    2081      249808 :   return isolate()->factory()->NewTuple2(validity_cell, stub);
    2082             : }
    2083             : 
    2084       15182 : void KeyedStoreIC::StoreElementPolymorphicHandlers(
    2085       50448 :     MapHandleList* receiver_maps, List<Handle<Object>>* handlers,
    2086             :     KeyedAccessStoreMode store_mode) {
    2087             :   DCHECK(store_mode == STANDARD_STORE ||
    2088             :          store_mode == STORE_AND_GROW_NO_TRANSITION ||
    2089             :          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
    2090             :          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
    2091             : 
    2092      100896 :   for (int i = 0; i < receiver_maps->length(); ++i) {
    2093       35266 :     Handle<Map> receiver_map(receiver_maps->at(i));
    2094             :     Handle<Object> handler;
    2095             :     Handle<Map> transitioned_map;
    2096             : 
    2097       70502 :     if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE ||
    2098       35236 :         receiver_map->DictionaryElementsInPrototypeChainOnly()) {
    2099             :       // TODO(mvstanton): Consider embedding store_mode in the state of the slow
    2100             :       // keyed store ic for uniformity.
    2101       25407 :       TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
    2102          45 :       handler = isolate()->builtins()->KeyedStoreIC_Slow();
    2103             : 
    2104             :     } else {
    2105             :       {
    2106             :         Map* tmap =
    2107       35221 :             receiver_map->FindElementsKindTransitionedMap(receiver_maps);
    2108       35221 :         if (tmap != nullptr) {
    2109        8238 :           if (receiver_map->is_stable()) {
    2110          30 :             receiver_map->NotifyLeafMapLayoutChange();
    2111             :           }
    2112             :           transitioned_map = handle(tmap);
    2113             :         }
    2114             :       }
    2115             : 
    2116             :       // TODO(mvstanton): The code below is doing pessimistic elements
    2117             :       // transitions. I would like to stop doing that and rely on Allocation
    2118             :       // Site Tracking to do a better job of ensuring the data types are what
    2119             :       // they need to be. Not all the elements are in place yet, pessimistic
    2120             :       // elements transitions are still important for performance.
    2121       35221 :       if (!transitioned_map.is_null()) {
    2122        8238 :         bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
    2123             :         ElementsKind elements_kind = receiver_map->elements_kind();
    2124        8238 :         TRACE_HANDLER_STATS(isolate(),
    2125             :                             KeyedStoreIC_ElementsTransitionAndStoreStub);
    2126             :         Handle<Code> stub =
    2127             :             ElementsTransitionAndStoreStub(isolate(), elements_kind,
    2128             :                                            transitioned_map->elements_kind(),
    2129             :                                            is_js_array, store_mode)
    2130       16476 :                 .GetCode();
    2131             :         Handle<Object> validity_cell =
    2132        8238 :             Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
    2133        8238 :         if (validity_cell.is_null()) {
    2134             :           validity_cell = handle(Smi::kZero, isolate());
    2135             :         }
    2136        8238 :         Handle<WeakCell> transition = Map::WeakCellForMap(transitioned_map);
    2137             :         handler =
    2138        8238 :             isolate()->factory()->NewTuple3(transition, stub, validity_cell);
    2139             :       } else {
    2140       26983 :         handler = StoreElementHandler(receiver_map, store_mode);
    2141             :       }
    2142             :     }
    2143             :     DCHECK(!handler.is_null());
    2144       35266 :     handlers->Add(handler);
    2145             :   }
    2146       15182 : }
    2147             : 
    2148      409926 : bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
    2149      409926 :   uint32_t length = 0;
    2150      409926 :   if (receiver->IsJSArray()) {
    2151             :     JSArray::cast(*receiver)->length()->ToArrayLength(&length);
    2152             :   } else {
    2153       45657 :     length = static_cast<uint32_t>(receiver->elements()->length());
    2154             :   }
    2155      409926 :   return index >= length;
    2156             : }
    2157             : 
    2158             : 
    2159      409926 : static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
    2160             :                                          uint32_t index, Handle<Object> value) {
    2161      409926 :   bool oob_access = IsOutOfBoundsAccess(receiver, index);
    2162             :   // Don't consider this a growing store if the store would send the receiver to
    2163             :   // dictionary mode.
    2164      596391 :   bool allow_growth = receiver->IsJSArray() && oob_access &&
    2165      186465 :                       !receiver->WouldConvertToSlowElements(index);
    2166      409926 :   if (allow_growth) {
    2167             :     // Handle growing array in stub if necessary.
    2168      185296 :     if (receiver->HasFastSmiElements()) {
    2169       24453 :       if (value->IsHeapNumber()) {
    2170             :         return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
    2171             :       }
    2172       23916 :       if (value->IsHeapObject()) {
    2173             :         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
    2174             :       }
    2175      160843 :     } else if (receiver->HasFastDoubleElements()) {
    2176         655 :       if (!value->IsSmi() && !value->IsHeapNumber()) {
    2177             :         return STORE_AND_GROW_TRANSITION_TO_OBJECT;
    2178             :       }
    2179             :     }
    2180             :     return STORE_AND_GROW_NO_TRANSITION;
    2181             :   } else {
    2182             :     // Handle only in-bounds elements accesses.
    2183      224630 :     if (receiver->HasFastSmiElements()) {
    2184      117423 :       if (value->IsHeapNumber()) {
    2185             :         return STORE_TRANSITION_TO_DOUBLE;
    2186      113522 :       } else if (value->IsHeapObject()) {
    2187             :         return STORE_TRANSITION_TO_OBJECT;
    2188             :       }
    2189      107207 :     } else if (receiver->HasFastDoubleElements()) {
    2190       11700 :       if (!value->IsSmi() && !value->IsHeapNumber()) {
    2191             :         return STORE_TRANSITION_TO_OBJECT;
    2192             :       }
    2193             :     }
    2194      512094 :     if (!FLAG_trace_external_array_abuse &&
    2195      198787 :         receiver->map()->has_fixed_typed_array_elements() && oob_access) {
    2196             :       return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
    2197             :     }
    2198      170046 :     Heap* heap = receiver->GetHeap();
    2199      170046 :     if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
    2200             :       return STORE_NO_TRANSITION_HANDLE_COW;
    2201             :     } else {
    2202      169052 :       return STANDARD_STORE;
    2203             :     }
    2204             :   }
    2205             : }
    2206             : 
    2207             : 
    2208      702538 : MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
    2209             :                                         Handle<Object> key,
    2210             :                                         Handle<Object> value) {
    2211             :   // TODO(verwaest): Let SetProperty do the migration, since storing a property
    2212             :   // might deprecate the current map again, if value does not fit.
    2213      702538 :   if (MigrateDeprecated(object)) {
    2214             :     Handle<Object> result;
    2215     2083351 :     ASSIGN_RETURN_ON_EXCEPTION(
    2216             :         isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
    2217             :                                                       value, language_mode()),
    2218             :         Object);
    2219             :     return result;
    2220             :   }
    2221             : 
    2222             :   // Check for non-string values that can be converted into an
    2223             :   // internalized string directly or is representable as a smi.
    2224      702538 :   key = TryConvertKey(key, isolate());
    2225             : 
    2226             :   Handle<Object> store_handle;
    2227             : 
    2228             :   uint32_t index;
    2229      940500 :   if ((key->IsInternalizedString() &&
    2230     1406507 :        !String::cast(*key)->AsArrayIndex(&index)) ||
    2231             :       key->IsSymbol()) {
    2232      568686 :     ASSIGN_RETURN_ON_EXCEPTION(
    2233             :         isolate(), store_handle,
    2234             :         StoreIC::Store(object, Handle<Name>::cast(key), value,
    2235             :                        JSReceiver::MAY_BE_STORE_FROM_KEYED),
    2236             :         Object);
    2237      282647 :     if (!is_vector_set()) {
    2238          99 :       ConfigureVectorState(MEGAMORPHIC, key);
    2239             :       TRACE_GENERIC_IC("unhandled internalized string key");
    2240          99 :       TRACE_IC("StoreIC", key);
    2241             :     }
    2242             :     return store_handle;
    2243             :   }
    2244             : 
    2245      836011 :   bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
    2246      835968 :                 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
    2247      835774 :   if (use_ic && !object->IsSmi()) {
    2248             :     // Don't use ICs for maps of the objects in Array's prototype chain. We
    2249             :     // expect to be able to trap element sets to objects with those maps in
    2250             :     // the runtime to enable optimization of element hole access.
    2251             :     Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
    2252      416927 :     if (heap_object->map()->IsMapInArrayPrototypeChain()) {
    2253             :       TRACE_GENERIC_IC("map in array prototype");
    2254             :       use_ic = false;
    2255             :     }
    2256             :   }
    2257             : 
    2258             :   Handle<Map> old_receiver_map;
    2259             :   bool is_arguments = false;
    2260             :   bool key_is_valid_index = false;
    2261             :   KeyedAccessStoreMode store_mode = STANDARD_STORE;
    2262      834685 :   if (use_ic && object->IsJSObject()) {
    2263             :     Handle<JSObject> receiver = Handle<JSObject>::cast(object);
    2264             :     old_receiver_map = handle(receiver->map(), isolate());
    2265             :     is_arguments = receiver->IsJSArgumentsObject();
    2266      414785 :     if (!is_arguments) {
    2267      823445 :       key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0;
    2268      412910 :       if (key_is_valid_index) {
    2269      409926 :         uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
    2270      409926 :         store_mode = GetStoreMode(receiver, index, value);
    2271             :       }
    2272             :     }
    2273             :   }
    2274             : 
    2275             :   DCHECK(store_handle.is_null());
    2276     1254585 :   ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
    2277             :                              Runtime::SetObjectProperty(isolate(), object, key,
    2278             :                                                         value, language_mode()),
    2279             :                              Object);
    2280             : 
    2281      265186 :   if (use_ic) {
    2282      263521 :     if (!old_receiver_map.is_null()) {
    2283      262620 :       if (is_arguments) {
    2284             :         TRACE_GENERIC_IC("arguments receiver");
    2285      260745 :       } else if (key_is_valid_index) {
    2286             :         // We should go generic if receiver isn't a dictionary, but our
    2287             :         // prototype chain does have dictionary elements. This ensures that
    2288             :         // other non-dictionary receivers in the polymorphic case benefit
    2289             :         // from fast path keyed stores.
    2290      258735 :         if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) {
    2291      247830 :           UpdateStoreElement(old_receiver_map, store_mode);
    2292             :         } else {
    2293             :           TRACE_GENERIC_IC("dictionary or proxy prototype");
    2294             :         }
    2295             :       } else {
    2296             :         TRACE_GENERIC_IC("non-smi-like key");
    2297             :       }
    2298             :     } else {
    2299             :       TRACE_GENERIC_IC("non-JSObject receiver");
    2300             :     }
    2301             :   }
    2302             : 
    2303      265186 :   if (!is_vector_set()) {
    2304       20814 :     ConfigureVectorState(MEGAMORPHIC, key);
    2305             :   }
    2306      265186 :   TRACE_IC("StoreIC", key);
    2307             : 
    2308             :   return store_handle;
    2309             : }
    2310             : 
    2311             : 
    2312             : #undef TRACE_IC
    2313             : 
    2314             : 
    2315             : // ----------------------------------------------------------------------------
    2316             : // Static IC stub generators.
    2317             : //
    2318             : 
    2319             : // Used from ic-<arch>.cc.
    2320     8719557 : RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
    2321     4359779 :   HandleScope scope(isolate);
    2322             :   DCHECK_EQ(4, args.length());
    2323             :   // Runtime functions don't follow the IC's calling convention.
    2324     4359779 :   Handle<Object> receiver = args.at(0);
    2325     4359779 :   Handle<Name> key = args.at<Name>(1);
    2326     4359779 :   Handle<Smi> slot = args.at<Smi>(2);
    2327     4359779 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
    2328     4359779 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2329             :   // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
    2330             :   // LoadIC miss handler if the handler misses. Since the vector Nexus is
    2331             :   // set up outside the IC, handle that here.
    2332     4359778 :   FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2333     4359778 :   if (IsLoadICKind(kind)) {
    2334     4359620 :     LoadICNexus nexus(vector, vector_slot);
    2335     8719240 :     LoadIC ic(isolate, &nexus);
    2336     4359622 :     ic.UpdateState(receiver, key);
    2337    13078864 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2338             : 
    2339         158 :   } else if (IsLoadGlobalICKind(kind)) {
    2340             :     DCHECK_EQ(isolate->native_context()->global_proxy(), *receiver);
    2341         158 :     receiver = isolate->global_object();
    2342         158 :     LoadGlobalICNexus nexus(vector, vector_slot);
    2343         316 :     LoadGlobalIC ic(isolate, &nexus);
    2344         158 :     ic.UpdateState(receiver, key);
    2345         474 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
    2346             : 
    2347             :   } else {
    2348             :     DCHECK(IsKeyedLoadICKind(kind));
    2349           0 :     KeyedLoadICNexus nexus(vector, vector_slot);
    2350           0 :     KeyedLoadIC ic(isolate, &nexus);
    2351           0 :     ic.UpdateState(receiver, key);
    2352           0 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2353     4359779 :   }
    2354             : }
    2355             : 
    2356             : // Used from ic-<arch>.cc.
    2357     4188843 : RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
    2358     2094421 :   HandleScope scope(isolate);
    2359             :   DCHECK_EQ(3, args.length());
    2360             :   // Runtime functions don't follow the IC's calling convention.
    2361     2094422 :   Handle<JSGlobalObject> global = isolate->global_object();
    2362     2094422 :   Handle<String> name = args.at<String>(0);
    2363     2094422 :   Handle<Smi> slot = args.at<Smi>(1);
    2364     2094422 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2365     2094421 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2366             : 
    2367     4188844 :   LoadGlobalICNexus nexus(vector, vector_slot);
    2368     4188844 :   LoadGlobalIC ic(isolate, &nexus);
    2369     2094422 :   ic.UpdateState(global, name);
    2370             : 
    2371             :   Handle<Object> result;
    2372     4188844 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
    2373     2094422 :   return *result;
    2374             : }
    2375             : 
    2376        1736 : RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
    2377         868 :   HandleScope scope(isolate);
    2378             :   DCHECK_EQ(3, args.length());
    2379        1736 :   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
    2380             : 
    2381         868 :   Handle<Context> native_context = isolate->native_context();
    2382             :   Handle<ScriptContextTable> script_contexts(
    2383         868 :       native_context->script_context_table());
    2384             : 
    2385             :   ScriptContextTable::LookupResult lookup_result;
    2386         868 :   if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
    2387             :     Handle<Context> script_context = ScriptContextTable::GetContext(
    2388           0 :         script_contexts, lookup_result.context_index);
    2389             :     Handle<Object> result =
    2390           0 :         FixedArray::get(*script_context, lookup_result.slot_index, isolate);
    2391           0 :     if (*result == isolate->heap()->the_hole_value()) {
    2392           0 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2393             :           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
    2394             :     }
    2395             :     return *result;
    2396             :   }
    2397             : 
    2398         868 :   Handle<JSGlobalObject> global(native_context->global_object(), isolate);
    2399             :   Handle<Object> result;
    2400         868 :   bool is_found = false;
    2401        1736 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    2402             :       isolate, result,
    2403             :       Runtime::GetObjectProperty(isolate, global, name, &is_found));
    2404         868 :   if (!is_found) {
    2405           0 :     Handle<Smi> slot = args.at<Smi>(1);
    2406           0 :     Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2407           0 :     FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2408           0 :     FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2409             :     // It is actually a LoadGlobalICs here but the predicate handles this case
    2410             :     // properly.
    2411           0 :     if (LoadIC::ShouldThrowReferenceError(kind)) {
    2412           0 :       THROW_NEW_ERROR_RETURN_FAILURE(
    2413             :           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
    2414             :     }
    2415             :   }
    2416         868 :   return *result;
    2417             : }
    2418             : 
    2419             : // Used from ic-<arch>.cc
    2420     1408136 : RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
    2421      704068 :   HandleScope scope(isolate);
    2422             :   DCHECK_EQ(4, args.length());
    2423             :   // Runtime functions don't follow the IC's calling convention.
    2424      704068 :   Handle<Object> receiver = args.at(0);
    2425      704068 :   Handle<Object> key = args.at(1);
    2426      704068 :   Handle<Smi> slot = args.at<Smi>(2);
    2427      704068 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(3);
    2428      704068 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2429     1408136 :   KeyedLoadICNexus nexus(vector, vector_slot);
    2430     1408136 :   KeyedLoadIC ic(isolate, &nexus);
    2431      704068 :   ic.UpdateState(receiver, key);
    2432     2112204 :   RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
    2433             : }
    2434             : 
    2435             : // Used from ic-<arch>.cc.
    2436    11791868 : RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
    2437     5895934 :   HandleScope scope(isolate);
    2438             :   DCHECK_EQ(5, args.length());
    2439             :   // Runtime functions don't follow the IC's calling convention.
    2440     5895934 :   Handle<Object> value = args.at(0);
    2441     5895934 :   Handle<Smi> slot = args.at<Smi>(1);
    2442     5895934 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2443     5895934 :   Handle<Object> receiver = args.at(3);
    2444     5895934 :   Handle<Name> key = args.at<Name>(4);
    2445     5895934 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2446     5895934 :   FeedbackSlotKind kind = vector->GetKind(vector_slot);
    2447     5895934 :   if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) {
    2448     4204991 :     StoreICNexus nexus(vector, vector_slot);
    2449     8409983 :     StoreIC ic(isolate, &nexus);
    2450     4204991 :     ic.UpdateState(receiver, key);
    2451    12614974 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2452     1690942 :   } else if (IsStoreGlobalICKind(kind)) {
    2453     1690942 :     StoreICNexus nexus(vector, vector_slot);
    2454     3381884 :     StoreGlobalIC ic(isolate, &nexus);
    2455     1690942 :     ic.UpdateState(receiver, key);
    2456     5072826 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2457             :   } else {
    2458             :     DCHECK(IsKeyedStoreICKind(kind));
    2459           0 :     KeyedStoreICNexus nexus(vector, vector_slot);
    2460           0 :     KeyedStoreIC ic(isolate, &nexus);
    2461           0 :     ic.UpdateState(receiver, key);
    2462           0 :     RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2463     5895934 :   }
    2464             : }
    2465             : 
    2466             : // Used from ic-<arch>.cc.
    2467     1405076 : RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
    2468      702538 :   HandleScope scope(isolate);
    2469             :   DCHECK_EQ(5, args.length());
    2470             :   // Runtime functions don't follow the IC's calling convention.
    2471      702538 :   Handle<Object> value = args.at(0);
    2472      702538 :   Handle<Smi> slot = args.at<Smi>(1);
    2473      702538 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2474      702538 :   Handle<Object> receiver = args.at(3);
    2475      702538 :   Handle<Object> key = args.at(4);
    2476      702538 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2477     1405076 :   KeyedStoreICNexus nexus(vector, vector_slot);
    2478     1405076 :   KeyedStoreIC ic(isolate, &nexus);
    2479      702538 :   ic.UpdateState(receiver, key);
    2480     2107614 :   RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
    2481             : }
    2482             : 
    2483             : 
    2484     2036558 : RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
    2485     1018279 :   HandleScope scope(isolate);
    2486             :   DCHECK_EQ(5, args.length());
    2487             :   // Runtime functions don't follow the IC's calling convention.
    2488     1018279 :   Handle<Object> value = args.at(0);
    2489     1018279 :   Handle<Smi> slot = args.at<Smi>(1);
    2490     1018279 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2491     1018279 :   Handle<Object> object = args.at(3);
    2492     1018279 :   Handle<Object> key = args.at(4);
    2493     1018279 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2494     1018279 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2495     2036558 :   RETURN_RESULT_OR_FAILURE(
    2496             :       isolate,
    2497     1018279 :       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
    2498             : }
    2499             : 
    2500             : 
    2501        2622 : RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
    2502        1311 :   HandleScope scope(isolate);
    2503             :   DCHECK_EQ(6, args.length());
    2504             :   // Runtime functions don't follow the IC's calling convention.
    2505        1311 :   Handle<Object> object = args.at(0);
    2506        1311 :   Handle<Object> key = args.at(1);
    2507        1311 :   Handle<Object> value = args.at(2);
    2508        1311 :   Handle<Map> map = args.at<Map>(3);
    2509        1311 :   Handle<Smi> slot = args.at<Smi>(4);
    2510        1311 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(5);
    2511        1311 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2512        1311 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2513        1311 :   if (object->IsJSObject()) {
    2514             :     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
    2515        1311 :                                      map->elements_kind());
    2516             :   }
    2517        2622 :   RETURN_RESULT_OR_FAILURE(
    2518             :       isolate,
    2519        1311 :       Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
    2520             : }
    2521             : 
    2522             : 
    2523      437808 : MaybeHandle<Object> BinaryOpIC::Transition(
    2524             :     Handle<AllocationSite> allocation_site, Handle<Object> left,
    2525             :     Handle<Object> right) {
    2526     2170408 :   BinaryOpICState state(isolate(), extra_ic_state());
    2527             : 
    2528             :   // Compute the actual result using the builtin for the binary operation.
    2529             :   Handle<Object> result;
    2530      437808 :   switch (state.op()) {
    2531             :     default:
    2532           0 :       UNREACHABLE();
    2533             :     case Token::ADD:
    2534      452106 :       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    2535             :                                  Object::Add(isolate(), left, right), Object);
    2536             :       break;
    2537             :     case Token::SUB:
    2538       38648 :       ASSIGN_RETURN_ON_EXCEPTION(
    2539             :           isolate(), result, Object::Subtract(isolate(), left, right), Object);
    2540             :       break;
    2541             :     case Token::MUL:
    2542       86458 :       ASSIGN_RETURN_ON_EXCEPTION(
    2543             :           isolate(), result, Object::Multiply(isolate(), left, right), Object);
    2544             :       break;
    2545             :     case Token::DIV:
    2546       23202 :       ASSIGN_RETURN_ON_EXCEPTION(
    2547             :           isolate(), result, Object::Divide(isolate(), left, right), Object);
    2548             :       break;
    2549             :     case Token::MOD:
    2550       10376 :       ASSIGN_RETURN_ON_EXCEPTION(
    2551             :           isolate(), result, Object::Modulus(isolate(), left, right), Object);
    2552             :       break;
    2553             :     case Token::BIT_OR:
    2554      128256 :       ASSIGN_RETURN_ON_EXCEPTION(
    2555             :           isolate(), result, Object::BitwiseOr(isolate(), left, right), Object);
    2556             :       break;
    2557             :     case Token::BIT_AND:
    2558       39192 :       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    2559             :                                  Object::BitwiseAnd(isolate(), left, right),
    2560             :                                  Object);
    2561             :       break;
    2562             :     case Token::BIT_XOR:
    2563       16552 :       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    2564             :                                  Object::BitwiseXor(isolate(), left, right),
    2565             :                                  Object);
    2566             :       break;
    2567             :     case Token::SAR:
    2568       41772 :       ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
    2569             :                                  Object::ShiftRight(isolate(), left, right),
    2570             :                                  Object);
    2571             :       break;
    2572             :     case Token::SHR:
    2573       20614 :       ASSIGN_RETURN_ON_EXCEPTION(
    2574             :           isolate(), result, Object::ShiftRightLogical(isolate(), left, right),
    2575             :           Object);
    2576             :       break;
    2577             :     case Token::SHL:
    2578       18440 :       ASSIGN_RETURN_ON_EXCEPTION(
    2579             :           isolate(), result, Object::ShiftLeft(isolate(), left, right), Object);
    2580             :       break;
    2581             :   }
    2582             : 
    2583             :   // Do not try to update the target if the code was marked for lazy
    2584             :   // deoptimization. (Since we do not relocate addresses in these
    2585             :   // code objects, an attempt to access the target could fail.)
    2586      433809 :   if (AddressIsDeoptimizedCode()) {
    2587             :     return result;
    2588             :   }
    2589             : 
    2590             :   // Compute the new state.
    2591      433805 :   BinaryOpICState old_state(isolate(), target()->extra_ic_state());
    2592      433805 :   state.Update(left, right, result);
    2593             : 
    2594             :   // Check if we have a string operation here.
    2595             :   Handle<Code> new_target;
    2596      867152 :   if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
    2597             :     // Setup the allocation site on-demand.
    2598       46824 :     if (allocation_site.is_null()) {
    2599       46366 :       allocation_site = isolate()->factory()->NewAllocationSite();
    2600             :     }
    2601             : 
    2602             :     // Install the stub with an allocation site.
    2603             :     BinaryOpICWithAllocationSiteStub stub(isolate(), state);
    2604       46824 :     new_target = stub.GetCodeCopyFromTemplate(allocation_site);
    2605             : 
    2606             :     // Sanity check the trampoline stub.
    2607             :     DCHECK_EQ(*allocation_site, new_target->FindFirstAllocationSite());
    2608             :   } else {
    2609             :     // Install the generic stub.
    2610             :     BinaryOpICStub stub(isolate(), state);
    2611      386981 :     new_target = stub.GetCode();
    2612             : 
    2613             :     // Sanity check the generic stub.
    2614             :     DCHECK_NULL(new_target->FindFirstAllocationSite());
    2615             :   }
    2616             :   set_target(*new_target);
    2617             : 
    2618      433805 :   if (FLAG_ic_stats &
    2619             :       v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
    2620             :     auto ic_stats = ICStats::instance();
    2621           0 :     ic_stats->Begin();
    2622             :     ICInfo& ic_info = ic_stats->Current();
    2623           0 :     ic_info.type = "BinaryOpIC";
    2624           0 :     ic_info.state = old_state.ToString();
    2625             :     ic_info.state += " => ";
    2626           0 :     ic_info.state += state.ToString();
    2627           0 :     JavaScriptFrame::CollectTopFrameForICStats(isolate());
    2628           0 :     ic_stats->End();
    2629      433805 :   } else if (FLAG_ic_stats) {
    2630             :     int line;
    2631             :     int column;
    2632           0 :     Address pc = GetAbstractPC(&line, &column);
    2633           0 :     LOG(isolate(),
    2634             :         BinaryOpIC(pc, line, column, *new_target, old_state.ToString().c_str(),
    2635             :                    state.ToString().c_str(),
    2636             :                    allocation_site.is_null() ? nullptr : *allocation_site));
    2637             :   }
    2638             : 
    2639             :   // Patch the inlined smi code as necessary.
    2640     1285248 :   if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
    2641      761632 :     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
    2642       69156 :   } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
    2643           0 :     PatchInlinedSmiCode(isolate(), address(), DISABLE_INLINED_SMI_CHECK);
    2644             :   }
    2645             : 
    2646             :   return result;
    2647             : }
    2648             : 
    2649             : 
    2650      874694 : RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
    2651      437347 :   HandleScope scope(isolate);
    2652             :   DCHECK_EQ(2, args.length());
    2653             :   typedef BinaryOpDescriptor Descriptor;
    2654      437347 :   Handle<Object> left = args.at(Descriptor::kLeft);
    2655      437347 :   Handle<Object> right = args.at(Descriptor::kRight);
    2656      874694 :   BinaryOpIC ic(isolate);
    2657      874694 :   RETURN_RESULT_OR_FAILURE(
    2658      437347 :       isolate, ic.Transition(Handle<AllocationSite>::null(), left, right));
    2659             : }
    2660             : 
    2661             : 
    2662         922 : RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
    2663         461 :   HandleScope scope(isolate);
    2664             :   DCHECK_EQ(3, args.length());
    2665             :   typedef BinaryOpWithAllocationSiteDescriptor Descriptor;
    2666             :   Handle<AllocationSite> allocation_site =
    2667         461 :       args.at<AllocationSite>(Descriptor::kAllocationSite);
    2668         461 :   Handle<Object> left = args.at(Descriptor::kLeft);
    2669         461 :   Handle<Object> right = args.at(Descriptor::kRight);
    2670         922 :   BinaryOpIC ic(isolate);
    2671         922 :   RETURN_RESULT_OR_FAILURE(isolate,
    2672         461 :                            ic.Transition(allocation_site, left, right));
    2673             : }
    2674             : 
    2675           2 : Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
    2676             :   CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
    2677             :                      CompareICState::UNINITIALIZED,
    2678             :                      CompareICState::UNINITIALIZED);
    2679           2 :   Code* code = NULL;
    2680           2 :   CHECK(stub.FindCodeInCache(&code));
    2681           2 :   return code;
    2682             : }
    2683             : 
    2684      272912 : Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
    2685     1071312 :   HandleScope scope(isolate());
    2686             :   CompareICStub old_stub(target()->stub_key(), isolate());
    2687             :   CompareICState::State new_left =
    2688      272912 :       CompareICState::NewInputState(old_stub.left(), x);
    2689             :   CompareICState::State new_right =
    2690      272912 :       CompareICState::NewInputState(old_stub.right(), y);
    2691             :   CompareICState::State state = CompareICState::TargetState(
    2692             :       isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_,
    2693      545824 :       HasInlinedSmiCode(address()), x, y);
    2694      272912 :   CompareICStub stub(isolate(), op_, new_left, new_right, state);
    2695      272912 :   if (state == CompareICState::KNOWN_RECEIVER) {
    2696             :     stub.set_known_map(
    2697             :         Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate()));
    2698             :   }
    2699      272912 :   Handle<Code> new_target = stub.GetCode();
    2700             :   set_target(*new_target);
    2701             : 
    2702      272912 :   if (FLAG_ic_stats &
    2703             :       v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
    2704             :     auto ic_stats = ICStats::instance();
    2705           0 :     ic_stats->Begin();
    2706             :     ICInfo& ic_info = ic_stats->Current();
    2707           0 :     ic_info.type = "CompareIC";
    2708           0 :     JavaScriptFrame::CollectTopFrameForICStats(isolate());
    2709           0 :     ic_info.state = "((";
    2710           0 :     ic_info.state += CompareICState::GetStateName(old_stub.left());
    2711             :     ic_info.state += "+";
    2712           0 :     ic_info.state += CompareICState::GetStateName(old_stub.right());
    2713             :     ic_info.state += "=";
    2714           0 :     ic_info.state += CompareICState::GetStateName(old_stub.state());
    2715             :     ic_info.state += ")->(";
    2716           0 :     ic_info.state += CompareICState::GetStateName(new_left);
    2717             :     ic_info.state += "+";
    2718           0 :     ic_info.state += CompareICState::GetStateName(new_right);
    2719             :     ic_info.state += "=";
    2720           0 :     ic_info.state += CompareICState::GetStateName(state);
    2721             :     ic_info.state += "))#";
    2722           0 :     ic_info.state += Token::Name(op_);
    2723           0 :     ic_stats->End();
    2724      272912 :   } else if (FLAG_ic_stats) {
    2725             :     int line;
    2726             :     int column;
    2727           0 :     Address pc = GetAbstractPC(&line, &column);
    2728           0 :     LOG(isolate(),
    2729             :         CompareIC(pc, line, column, *stub.GetCode(), Token::Name(op_),
    2730             :                   CompareICState::GetStateName(old_stub.left()),
    2731             :                   CompareICState::GetStateName(old_stub.right()),
    2732             :                   CompareICState::GetStateName(old_stub.state()),
    2733             :                   CompareICState::GetStateName(new_left),
    2734             :                   CompareICState::GetStateName(new_right),
    2735             :                   CompareICState::GetStateName(state)));
    2736             :   }
    2737             : 
    2738             :   // Activate inlined smi code.
    2739      272912 :   if (old_stub.state() == CompareICState::UNINITIALIZED) {
    2740      505152 :     PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
    2741             :   }
    2742             : 
    2743      272912 :   return *new_target;
    2744             : }
    2745             : 
    2746             : 
    2747             : // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
    2748      545824 : RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
    2749      272912 :   HandleScope scope(isolate);
    2750             :   DCHECK(args.length() == 3);
    2751      545824 :   CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
    2752      545824 :   return ic.UpdateCaches(args.at(0), args.at(1));
    2753             : }
    2754             : 
    2755             : 
    2756           0 : RUNTIME_FUNCTION(Runtime_Unreachable) {
    2757           0 :   UNREACHABLE();
    2758             :   CHECK(false);
    2759             :   return isolate->heap()->undefined_value();
    2760             : }
    2761             : 
    2762             : 
    2763      130693 : Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
    2764      261386 :   ToBooleanICStub stub(isolate(), extra_ic_state());
    2765      130693 :   ToBooleanHints old_hints = stub.hints();
    2766      130693 :   bool to_boolean_value = stub.UpdateStatus(object);
    2767      130693 :   ToBooleanHints new_hints = stub.hints();
    2768      130693 :   Handle<Code> code = stub.GetCode();
    2769             :   set_target(*code);
    2770             : 
    2771             :   // Note: Although a no-op transition is semantically OK, it is hinting at a
    2772             :   // bug somewhere in our state transition machinery.
    2773             :   DCHECK_NE(old_hints, new_hints);
    2774      130693 :   if (V8_UNLIKELY(FLAG_ic_stats)) {
    2775           0 :     if (FLAG_ic_stats &
    2776             :         v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) {
    2777             :       auto ic_stats = ICStats::instance();
    2778           0 :       ic_stats->Begin();
    2779             :       ICInfo& ic_info = ic_stats->Current();
    2780           0 :       ic_info.type = "ToBooleanIC";
    2781           0 :       ic_info.state = ToString(old_hints);
    2782             :       ic_info.state += "=>";
    2783           0 :       ic_info.state += ToString(new_hints);
    2784           0 :       ic_stats->End();
    2785             :     } else {
    2786             :       int line;
    2787             :       int column;
    2788           0 :       Address pc = GetAbstractPC(&line, &column);
    2789           0 :       LOG(isolate(),
    2790             :           ToBooleanIC(pc, line, column, *code, ToString(old_hints).c_str(),
    2791             :                       ToString(new_hints).c_str()));
    2792             :     }
    2793             :   }
    2794             : 
    2795      261386 :   return isolate()->factory()->ToBoolean(to_boolean_value);
    2796             : }
    2797             : 
    2798             : 
    2799      261386 : RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
    2800             :   DCHECK(args.length() == 1);
    2801      130693 :   HandleScope scope(isolate);
    2802      130693 :   Handle<Object> object = args.at(0);
    2803      261386 :   ToBooleanIC ic(isolate);
    2804      392079 :   return *ic.ToBoolean(object);
    2805             : }
    2806             : 
    2807             : 
    2808    77105994 : RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
    2809    38552997 :   Handle<JSObject> receiver = args.at<JSObject>(0);
    2810    38552997 :   Handle<JSObject> holder = args.at<JSObject>(1);
    2811    38552997 :   Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
    2812    38552997 :   Handle<Name> name = args.at<Name>(3);
    2813    38552997 :   Handle<Object> value = args.at(4);
    2814    77105994 :   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
    2815    38552997 :   HandleScope scope(isolate);
    2816             : 
    2817    38552997 :   if (V8_UNLIKELY(FLAG_runtime_stats)) {
    2818           0 :     RETURN_RESULT_OR_FAILURE(
    2819             :         isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
    2820             :                                             language_mode));
    2821             :   }
    2822             : 
    2823             :   Handle<AccessorInfo> callback(
    2824             :       callback_or_cell->IsWeakCell()
    2825    37291104 :           ? AccessorInfo::cast(WeakCell::cast(*callback_or_cell)->value())
    2826    38552997 :           : AccessorInfo::cast(*callback_or_cell));
    2827             : 
    2828             :   DCHECK(callback->IsCompatibleReceiver(*receiver));
    2829             : 
    2830    38552997 :   Address setter_address = v8::ToCData<Address>(callback->setter());
    2831             :   v8::AccessorNameSetterCallback fun =
    2832    38552997 :       FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
    2833             :   DCHECK(fun != NULL);
    2834             : 
    2835             :   Object::ShouldThrow should_throw =
    2836    38552997 :       is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
    2837             :   PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
    2838    77105994 :                                         *holder, should_throw);
    2839    38552997 :   custom_args.Call(fun, name, value);
    2840    38552997 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2841    38552997 :   return *value;
    2842             : }
    2843             : 
    2844             : 
    2845             : /**
    2846             :  * Loads a property with an interceptor performing post interceptor
    2847             :  * lookup if interceptor failed.
    2848             :  */
    2849      589584 : RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
    2850      294792 :   HandleScope scope(isolate);
    2851             :   DCHECK_EQ(5, args.length());
    2852      294792 :   Handle<Name> name = args.at<Name>(0);
    2853      294792 :   Handle<Object> receiver = args.at(1);
    2854      294792 :   Handle<JSObject> holder = args.at<JSObject>(2);
    2855             : 
    2856      294792 :   if (!receiver->IsJSReceiver()) {
    2857          12 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    2858             :         isolate, receiver, Object::ConvertReceiver(isolate, receiver));
    2859             :   }
    2860             : 
    2861      294792 :   InterceptorInfo* interceptor = holder->GetNamedInterceptor();
    2862             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2863      589584 :                                       *holder, Object::DONT_THROW);
    2864             : 
    2865             :   v8::GenericNamedPropertyGetterCallback getter =
    2866             :       v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
    2867      294792 :           interceptor->getter());
    2868      294792 :   Handle<Object> result = arguments.Call(getter, name);
    2869             : 
    2870      294792 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2871             : 
    2872      294778 :   if (!result.is_null()) return *result;
    2873             : 
    2874      202749 :   LookupIterator it(receiver, name, holder);
    2875             :   // Skip any lookup work until we hit the (possibly non-masking) interceptor.
    2876      608247 :   while (it.state() != LookupIterator::INTERCEPTOR ||
    2877      405498 :          !it.GetHolder<JSObject>().is_identical_to(holder)) {
    2878             :     DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
    2879           0 :     it.Next();
    2880             :   }
    2881             :   // Skip past the interceptor.
    2882      202749 :   it.Next();
    2883      405498 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
    2884             : 
    2885      202735 :   if (it.IsFound()) return *result;
    2886             : 
    2887        7510 :   Handle<Smi> slot = args.at<Smi>(3);
    2888        7510 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(4);
    2889        7510 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2890        7510 :   FeedbackSlotKind slot_kind = vector->GetKind(vector_slot);
    2891             :   // It could actually be any kind of load IC slot here but the predicate
    2892             :   // handles all the cases properly.
    2893        7510 :   if (!LoadIC::ShouldThrowReferenceError(slot_kind)) {
    2894        7356 :     return isolate->heap()->undefined_value();
    2895             :   }
    2896             : 
    2897             :   // Throw a reference error.
    2898         462 :   THROW_NEW_ERROR_RETURN_FAILURE(
    2899      294792 :       isolate, NewReferenceError(MessageTemplate::kNotDefined, it.name()));
    2900             : }
    2901             : 
    2902             : 
    2903     1274710 : RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
    2904      637355 :   HandleScope scope(isolate);
    2905             :   DCHECK_EQ(5, args.length());
    2906             :   // Runtime functions don't follow the IC's calling convention.
    2907      637355 :   Handle<Object> value = args.at(0);
    2908      637355 :   Handle<Smi> slot = args.at<Smi>(1);
    2909      637355 :   Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
    2910      637355 :   Handle<JSObject> receiver = args.at<JSObject>(3);
    2911      637355 :   Handle<Name> name = args.at<Name>(4);
    2912      637355 :   FeedbackSlot vector_slot = vector->ToSlot(slot->value());
    2913      637355 :   LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
    2914             : 
    2915             :   DCHECK(receiver->HasNamedInterceptor());
    2916      637355 :   InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
    2917             :   DCHECK(!interceptor->non_masking());
    2918             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2919     1274710 :                                       *receiver, Object::DONT_THROW);
    2920             : 
    2921             :   v8::GenericNamedPropertySetterCallback setter =
    2922             :       v8::ToCData<v8::GenericNamedPropertySetterCallback>(
    2923      637355 :           interceptor->setter());
    2924      637355 :   Handle<Object> result = arguments.Call(setter, name, value);
    2925      637355 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2926      637348 :   if (!result.is_null()) return *value;
    2927             : 
    2928      350294 :   LookupIterator it(receiver, name, receiver);
    2929             :   // Skip past any access check on the receiver.
    2930      350294 :   if (it.state() == LookupIterator::ACCESS_CHECK) {
    2931             :     DCHECK(it.HasAccess());
    2932           0 :     it.Next();
    2933             :   }
    2934             :   // Skip past the interceptor on the receiver.
    2935             :   DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
    2936      350294 :   it.Next();
    2937             : 
    2938      350294 :   MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
    2939             :                                    JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
    2940             :                isolate->heap()->exception());
    2941      637355 :   return *value;
    2942             : }
    2943             : 
    2944             : 
    2945        5208 : RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
    2946             :   // TODO(verwaest): This should probably get the holder and receiver as input.
    2947        2604 :   HandleScope scope(isolate);
    2948        2604 :   Handle<JSObject> receiver = args.at<JSObject>(0);
    2949             :   DCHECK(args.smi_at(1) >= 0);
    2950        2604 :   uint32_t index = args.smi_at(1);
    2951             : 
    2952        2604 :   InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
    2953             :   PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
    2954        5208 :                                       *receiver, Object::DONT_THROW);
    2955             : 
    2956             :   v8::IndexedPropertyGetterCallback getter =
    2957        2604 :       v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
    2958        2604 :   Handle<Object> result = arguments.Call(getter, index);
    2959             : 
    2960        2604 :   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    2961             : 
    2962        2604 :   if (result.is_null()) {
    2963           0 :     LookupIterator it(isolate, receiver, index, receiver);
    2964             :     DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
    2965           0 :     it.Next();
    2966           0 :     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
    2967             :                                        Object::GetProperty(&it));
    2968             :   }
    2969             : 
    2970        2604 :   return *result;
    2971             : }
    2972             : }  // namespace internal
    2973             : }  // namespace v8

Generated by: LCOV version 1.10