LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1306 1306 100.0 %
Date: 2017-10-20 Functions: 64 64 100.0 %

          Line data    Source code
       1             : // Copyright 2016 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/accessor-assembler.h"
       6             : 
       7             : #include "src/code-factory.h"
       8             : #include "src/code-stubs.h"
       9             : #include "src/counters.h"
      10             : #include "src/ic/handler-configuration.h"
      11             : #include "src/ic/ic.h"
      12             : #include "src/ic/stub-cache.h"
      13             : #include "src/objects-inl.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : using compiler::CodeAssemblerState;
      19             : using compiler::Node;
      20             : 
      21             : //////////////////// Private helpers.
      22             : 
      23         217 : Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector,
      24             :                                             Node* receiver_map,
      25             :                                             Label* if_handler,
      26             :                                             Variable* var_handler,
      27             :                                             Label* if_miss) {
      28         217 :   Comment("TryMonomorphicCase");
      29             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
      30             : 
      31             :   // TODO(ishell): add helper class that hides offset computations for a series
      32             :   // of loads.
      33             :   CSA_ASSERT(this, IsFeedbackVector(vector), vector);
      34             :   int32_t header_size = FeedbackVector::kFeedbackSlotsOffset - kHeapObjectTag;
      35             :   // Adding |header_size| with a separate IntPtrAdd rather than passing it
      36             :   // into ElementOffsetFromIndex() allows it to be folded into a single
      37             :   // [base, index, offset] indirect memory access on x64.
      38         217 :   Node* offset = ElementOffsetFromIndex(slot, HOLEY_ELEMENTS, SMI_PARAMETERS);
      39             :   Node* feedback = Load(MachineType::AnyTagged(), vector,
      40         651 :                         IntPtrAdd(offset, IntPtrConstant(header_size)));
      41             : 
      42             :   // Try to quickly handle the monomorphic case without knowing for sure
      43             :   // if we have a weak cell in feedback. We do know it's safe to look
      44             :   // at WeakCell::kValueOffset.
      45         434 :   GotoIf(WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)),
      46         434 :          if_miss);
      47             : 
      48             :   Node* handler =
      49             :       Load(MachineType::AnyTagged(), vector,
      50         651 :            IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize)));
      51             : 
      52         217 :   var_handler->Bind(handler);
      53         217 :   Goto(if_handler);
      54         217 :   return feedback;
      55             : }
      56             : 
      57         279 : void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map,
      58             :                                               Node* feedback, Label* if_handler,
      59             :                                               Variable* var_handler,
      60             :                                               Label* if_miss,
      61             :                                               int min_feedback_capacity) {
      62         279 :   Comment("HandlePolymorphicCase");
      63             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
      64             : 
      65             :   // Deferred so the unrolled case can omit frame construction in bytecode
      66             :   // handler.
      67             :   Label loop(this, Label::kDeferred);
      68             : 
      69             :   // Iterate {feedback} array.
      70             :   const int kEntrySize = 2;
      71             : 
      72             :   // Loading feedback's length is delayed until we need it when looking past
      73             :   // the first {min_feedback_capacity} (map, handler) pairs.
      74             :   Node* length = nullptr;
      75             :   CSA_ASSERT(this, SmiGreaterThanOrEqual(
      76             :                        LoadFixedArrayBaseLength(feedback),
      77             :                        SmiConstant(min_feedback_capacity * kEntrySize)));
      78             : 
      79             :   const int kUnrolledIterations = IC::kMaxPolymorphicMapCount;
      80        1395 :   for (int i = 0; i < kUnrolledIterations; i++) {
      81        1116 :     int map_index = i * kEntrySize;
      82        1116 :     int handler_index = i * kEntrySize + 1;
      83             : 
      84        1116 :     if (i >= min_feedback_capacity) {
      85        1178 :       if (length == nullptr) length = LoadFixedArrayBaseLength(feedback);
      86             :       GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), length),
      87        1860 :              if_miss);
      88             :     }
      89             : 
      90             :     Label next_entry(this);
      91             :     Node* cached_map =
      92        1116 :         LoadWeakCellValue(LoadFixedArrayElement(feedback, map_index));
      93        2232 :     GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
      94             : 
      95             :     // Found, now call handler.
      96        1116 :     Node* handler = LoadFixedArrayElement(feedback, handler_index);
      97        1116 :     var_handler->Bind(handler);
      98        1116 :     Goto(if_handler);
      99             : 
     100        1116 :     BIND(&next_entry);
     101        1116 :   }
     102         279 :   Goto(&loop);
     103             : 
     104             :   // Loop from {kUnrolledIterations}*kEntrySize to {length}.
     105         279 :   BIND(&loop);
     106         558 :   Node* start_index = IntPtrConstant(kUnrolledIterations * kEntrySize);
     107         558 :   Node* end_index = LoadAndUntagFixedArrayBaseLength(feedback);
     108             :   BuildFastLoop(
     109             :       start_index, end_index,
     110         279 :       [this, receiver_map, feedback, if_handler, var_handler](Node* index) {
     111             :         Node* cached_map =
     112         279 :             LoadWeakCellValue(LoadFixedArrayElement(feedback, index));
     113             : 
     114         279 :         Label next_entry(this);
     115         837 :         GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry);
     116             : 
     117             :         // Found, now call handler.
     118         279 :         Node* handler = LoadFixedArrayElement(feedback, index, kPointerSize);
     119         279 :         var_handler->Bind(handler);
     120         279 :         Goto(if_handler);
     121             : 
     122         279 :         BIND(&next_entry);
     123         279 :       },
     124         558 :       kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     125             :   // The loop falls through if no handler was found.
     126         279 :   Goto(if_miss);
     127         279 : }
     128             : 
     129         248 : void AccessorAssembler::HandleLoadICHandlerCase(
     130             :     const LoadICParameters* p, Node* handler, Label* miss,
     131             :     ExitPoint* exit_point, ElementSupport support_elements) {
     132         248 :   Comment("have_handler");
     133             : 
     134         248 :   VARIABLE(var_holder, MachineRepresentation::kTagged, p->receiver);
     135         496 :   VARIABLE(var_smi_handler, MachineRepresentation::kTagged, handler);
     136             : 
     137         248 :   Variable* vars[] = {&var_holder, &var_smi_handler};
     138         496 :   Label if_smi_handler(this, 2, vars);
     139         248 :   Label try_proto_handler(this, Label::kDeferred),
     140         248 :       call_handler(this, Label::kDeferred);
     141             : 
     142         496 :   Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
     143             : 
     144             :   // |handler| is a Smi, encoding what to do. See SmiHandler methods
     145             :   // for the encoding format.
     146         248 :   BIND(&if_smi_handler);
     147             :   {
     148             :     HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(),
     149         248 :                                miss, exit_point, false, support_elements);
     150             :   }
     151             : 
     152         248 :   BIND(&try_proto_handler);
     153             :   {
     154         744 :     GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
     155             :     HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler,
     156         248 :                                  &if_smi_handler, miss, exit_point, false);
     157             :   }
     158             : 
     159         248 :   BIND(&call_handler);
     160             :   {
     161             :     typedef LoadWithVectorDescriptor Descriptor;
     162             :     exit_point->ReturnCallStub(Descriptor(isolate()), handler, p->context,
     163         496 :                                p->receiver, p->name, p->slot, p->vector);
     164         248 :   }
     165         248 : }
     166             : 
     167        1209 : void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word,
     168             :                                         Variable* var_double_value,
     169             :                                         Label* rebox_double,
     170             :                                         ExitPoint* exit_point) {
     171        1209 :   Comment("field_load");
     172        1209 :   Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word);
     173             : 
     174        1209 :   Label inobject(this), out_of_object(this);
     175             :   Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject,
     176        1209 :          &out_of_object);
     177             : 
     178        1209 :   BIND(&inobject);
     179             :   {
     180             :     Label is_double(this);
     181        1209 :     GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
     182        1209 :     exit_point->Return(LoadObjectField(holder, offset));
     183             : 
     184        1209 :     BIND(&is_double);
     185             :     if (FLAG_unbox_double_fields) {
     186             :       var_double_value->Bind(
     187        1209 :           LoadObjectField(holder, offset, MachineType::Float64()));
     188             :     } else {
     189             :       Node* mutable_heap_number = LoadObjectField(holder, offset);
     190             :       var_double_value->Bind(LoadHeapNumberValue(mutable_heap_number));
     191             :     }
     192        1209 :     Goto(rebox_double);
     193             :   }
     194             : 
     195        1209 :   BIND(&out_of_object);
     196             :   {
     197             :     Label is_double(this);
     198        2418 :     Node* properties = LoadFastProperties(holder);
     199             :     Node* value = LoadObjectField(properties, offset);
     200        1209 :     GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
     201        1209 :     exit_point->Return(value);
     202             : 
     203        1209 :     BIND(&is_double);
     204        2418 :     var_double_value->Bind(LoadHeapNumberValue(value));
     205        1209 :     Goto(rebox_double);
     206        1209 :   }
     207        1209 : }
     208             : 
     209        1178 : void AccessorAssembler::HandleLoadICSmiHandlerCase(
     210             :     const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss,
     211             :     ExitPoint* exit_point, bool throw_reference_error_if_nonexistent,
     212             :     ElementSupport support_elements) {
     213        1178 :   VARIABLE(var_double_value, MachineRepresentation::kFloat64);
     214        1178 :   Label rebox_double(this, &var_double_value);
     215             : 
     216        2356 :   Node* handler_word = SmiUntag(smi_handler);
     217             :   Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word);
     218        1178 :   if (support_elements == kSupportElements) {
     219             :     Label property(this);
     220          62 :     GotoIfNot(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kElement)),
     221          62 :               &property);
     222             : 
     223          31 :     Comment("element_load");
     224          31 :     Node* intptr_index = TryToIntptr(p->name, miss);
     225          62 :     Node* elements = LoadElements(holder);
     226             :     Node* is_jsarray_condition =
     227             :         IsSetWord<LoadHandler::IsJsArrayBits>(handler_word);
     228             :     Node* elements_kind =
     229          31 :         DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word);
     230          31 :     Label if_hole(this), unimplemented_elements_kind(this);
     231             :     Label* out_of_bounds = miss;
     232             :     EmitElementLoad(holder, elements, elements_kind, intptr_index,
     233             :                     is_jsarray_condition, &if_hole, &rebox_double,
     234             :                     &var_double_value, &unimplemented_elements_kind,
     235          31 :                     out_of_bounds, miss, exit_point);
     236             : 
     237          31 :     BIND(&unimplemented_elements_kind);
     238             :     {
     239             :       // Smi handlers should only be installed for supported elements kinds.
     240             :       // Crash if we get here.
     241          31 :       DebugBreak();
     242          31 :       Goto(miss);
     243             :     }
     244             : 
     245          31 :     BIND(&if_hole);
     246             :     {
     247          31 :       Comment("convert hole");
     248          31 :       GotoIfNot(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss);
     249          62 :       GotoIf(IsArrayProtectorCellInvalid(), miss);
     250          62 :       exit_point->Return(UndefinedConstant());
     251             :     }
     252             : 
     253          31 :     BIND(&property);
     254          62 :     Comment("property_load");
     255             :   }
     256             : 
     257        1178 :   Label constant(this), field(this), normal(this, Label::kDeferred),
     258        1178 :       interceptor(this, Label::kDeferred), nonexistent(this),
     259        1178 :       accessor(this, Label::kDeferred), global(this, Label::kDeferred),
     260        1178 :       module_export(this, Label::kDeferred), proxy(this, Label::kDeferred);
     261        3534 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
     262             : 
     263        2356 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
     264        2356 :          &constant);
     265             : 
     266        2356 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
     267        2356 :          &nonexistent);
     268             : 
     269        2356 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)),
     270        2356 :          &normal);
     271             : 
     272        2356 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kAccessor)),
     273        2356 :          &accessor);
     274             : 
     275        2356 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kGlobal)),
     276        2356 :          &global);
     277             : 
     278        3534 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kProxy)), &proxy);
     279             : 
     280        2356 :   Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kModuleExport)),
     281        2356 :          &module_export, &interceptor);
     282             : 
     283        1178 :   BIND(&field);
     284             :   HandleLoadField(holder, handler_word, &var_double_value, &rebox_double,
     285        1178 :                   exit_point);
     286             : 
     287        1178 :   BIND(&nonexistent);
     288             :   // This is a handler for a load of a non-existent value.
     289        1178 :   if (throw_reference_error_if_nonexistent) {
     290             :     exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
     291         465 :                                   p->name);
     292             :   } else {
     293        1426 :     exit_point->Return(UndefinedConstant());
     294             :   }
     295             : 
     296        1178 :   BIND(&constant);
     297             :   {
     298        1178 :     Comment("constant_load");
     299        3534 :     Node* descriptors = LoadMapDescriptors(LoadMap(holder));
     300             :     Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word);
     301             :     Node* scaled_descriptor =
     302        3534 :         IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
     303             :     Node* value_index =
     304             :         IntPtrAdd(scaled_descriptor,
     305             :                   IntPtrConstant(DescriptorArray::kFirstIndex +
     306        3534 :                                  DescriptorArray::kEntryValueIndex));
     307             :     CSA_ASSERT(this,
     308             :                UintPtrLessThan(descriptor,
     309             :                                LoadAndUntagFixedArrayBaseLength(descriptors)));
     310        1178 :     Node* value = LoadFixedArrayElement(descriptors, value_index);
     311             : 
     312             :     Label if_accessor_info(this, Label::kDeferred);
     313             :     GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word),
     314        1178 :            &if_accessor_info);
     315        1178 :     exit_point->Return(value);
     316             : 
     317        1178 :     BIND(&if_accessor_info);
     318        1178 :     Callable callable = CodeFactory::ApiGetter(isolate());
     319             :     exit_point->ReturnCallStub(callable, p->context, p->receiver, holder,
     320        2356 :                                value);
     321             :   }
     322             : 
     323        1178 :   BIND(&normal);
     324             :   {
     325        1178 :     Comment("load_normal");
     326        2356 :     Node* properties = LoadSlowProperties(holder);
     327        1178 :     VARIABLE(var_name_index, MachineType::PointerRepresentation());
     328        1178 :     Label found(this, &var_name_index);
     329             :     NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
     330        1178 :                                          &var_name_index, miss);
     331        1178 :     BIND(&found);
     332             :     {
     333        1178 :       VARIABLE(var_details, MachineRepresentation::kWord32);
     334        2356 :       VARIABLE(var_value, MachineRepresentation::kTagged);
     335             :       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
     336        1178 :                                      &var_details, &var_value);
     337             :       Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
     338        1178 :                                          p->context, p->receiver, miss);
     339        2356 :       exit_point->Return(value);
     340        1178 :     }
     341             :   }
     342             : 
     343        1178 :   BIND(&accessor);
     344             :   {
     345        1178 :     Comment("accessor_load");
     346        3534 :     Node* descriptors = LoadMapDescriptors(LoadMap(holder));
     347             :     Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word);
     348             :     Node* scaled_descriptor =
     349        3534 :         IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
     350             :     Node* value_index =
     351             :         IntPtrAdd(scaled_descriptor,
     352             :                   IntPtrConstant(DescriptorArray::kFirstIndex +
     353        3534 :                                  DescriptorArray::kEntryValueIndex));
     354             :     CSA_ASSERT(this,
     355             :                UintPtrLessThan(descriptor,
     356             :                                LoadAndUntagFixedArrayBaseLength(descriptors)));
     357        1178 :     Node* accessor_pair = LoadFixedArrayElement(descriptors, value_index);
     358             :     CSA_ASSERT(this, IsAccessorPair(accessor_pair));
     359             :     Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
     360             :     CSA_ASSERT(this, Word32BinaryNot(IsTheHole(getter)));
     361             : 
     362        1178 :     Callable callable = CodeFactory::Call(isolate());
     363        1178 :     exit_point->Return(CallJS(callable, p->context, getter, p->receiver));
     364             :   }
     365             : 
     366        1178 :   BIND(&proxy);
     367             :   {
     368        1178 :     VARIABLE(var_index, MachineType::PointerRepresentation());
     369        2356 :     VARIABLE(var_unique, MachineRepresentation::kTagged);
     370             : 
     371        1178 :     Label if_index(this), if_unique_name(this),
     372        1178 :         to_name_failed(this, Label::kDeferred);
     373             : 
     374        1178 :     if (support_elements == kSupportElements) {
     375             :       TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
     376          31 :                 &to_name_failed);
     377             : 
     378          31 :       BIND(&if_unique_name);
     379             :       exit_point->ReturnCallStub(
     380             :           Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
     381          62 :           p->context, holder, var_unique.value(), p->receiver);
     382             : 
     383          31 :       BIND(&if_index);
     384             :       // TODO(mslekova): introduce TryToName that doesn't try to compute
     385             :       // the intptr index value
     386          31 :       Goto(&to_name_failed);
     387             : 
     388          31 :       BIND(&to_name_failed);
     389             :       exit_point->ReturnCallRuntime(Runtime::kGetPropertyWithReceiver,
     390          31 :                                     p->context, holder, p->name, p->receiver);
     391             : 
     392             :     } else {
     393             :       exit_point->ReturnCallStub(
     394             :           Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
     395        2294 :           p->context, holder, p->name, p->receiver);
     396        1178 :     }
     397             :   }
     398             : 
     399        1178 :   BIND(&global);
     400             :   {
     401             :     CSA_ASSERT(this, IsPropertyCell(holder));
     402             :     // Ensure the property cell doesn't contain the hole.
     403             :     Node* value = LoadObjectField(holder, PropertyCell::kValueOffset);
     404             :     Node* details =
     405        2356 :         LoadAndUntagToWord32ObjectField(holder, PropertyCell::kDetailsOffset);
     406        2356 :     GotoIf(IsTheHole(value), miss);
     407             : 
     408             :     exit_point->Return(
     409        1178 :         CallGetterIfAccessor(value, details, p->context, p->receiver, miss));
     410             :   }
     411             : 
     412        1178 :   BIND(&interceptor);
     413             :   {
     414        1178 :     Comment("load_interceptor");
     415             :     exit_point->ReturnCallRuntime(Runtime::kLoadPropertyWithInterceptor,
     416             :                                   p->context, p->name, p->receiver, holder,
     417        1178 :                                   p->slot, p->vector);
     418             :   }
     419             : 
     420        1178 :   BIND(&module_export);
     421             :   {
     422        1178 :     Comment("module export");
     423             :     Node* index = DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);
     424             :     Node* module =
     425             :         LoadObjectField(p->receiver, JSModuleNamespace::kModuleOffset,
     426        2356 :                         MachineType::TaggedPointer());
     427             :     Node* exports = LoadObjectField(module, Module::kExportsOffset,
     428        1178 :                                     MachineType::TaggedPointer());
     429        1178 :     Node* cell = LoadFixedArrayElement(exports, index);
     430             :     // The handler is only installed for exports that exist.
     431             :     CSA_ASSERT(this, IsCell(cell));
     432        1178 :     Node* value = LoadCellValue(cell);
     433             :     Label is_the_hole(this, Label::kDeferred);
     434        2356 :     GotoIf(IsTheHole(value), &is_the_hole);
     435        1178 :     exit_point->Return(value);
     436             : 
     437        1178 :     BIND(&is_the_hole);
     438             :     {
     439        2356 :       Node* message = SmiConstant(MessageTemplate::kNotDefined);
     440             :       exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
     441        1178 :                                     message, p->name);
     442        1178 :     }
     443             :   }
     444             : 
     445        1178 :   BIND(&rebox_double);
     446        4712 :   exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value()));
     447        1178 : }
     448             : 
     449         682 : void AccessorAssembler::HandleLoadICProtoHandlerCase(
     450             :     const LoadICParameters* p, Node* handler, Variable* var_holder,
     451             :     Variable* var_smi_handler, Label* if_smi_handler, Label* miss,
     452             :     ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) {
     453             :   DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep());
     454             :   DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep());
     455             : 
     456             :   // IC dispatchers rely on these assumptions to be held.
     457             :   STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset);
     458             :   DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex),
     459             :             LoadHandler::kSmiHandlerOffset);
     460             :   DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex),
     461             :             LoadHandler::kValidityCellOffset);
     462             : 
     463             :   // Both FixedArray and Tuple3 handlers have validity cell at the same offset.
     464         682 :   Label validity_cell_check_done(this);
     465             :   Node* validity_cell =
     466         682 :       LoadObjectField(handler, LoadHandler::kValidityCellOffset);
     467        1364 :   GotoIf(WordEqual(validity_cell, IntPtrConstant(0)),
     468        1364 :          &validity_cell_check_done);
     469             :   Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
     470        1364 :   GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
     471         682 :          miss);
     472         682 :   Goto(&validity_cell_check_done);
     473             : 
     474         682 :   BIND(&validity_cell_check_done);
     475             :   Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset);
     476             :   CSA_ASSERT(this, TaggedIsSmi(smi_handler));
     477        1364 :   Node* handler_flags = SmiUntag(smi_handler);
     478             : 
     479         682 :   Label check_prototypes(this);
     480             :   GotoIfNot(IsSetWord<LoadHandler::LookupOnReceiverBits>(handler_flags),
     481         682 :             &check_prototypes);
     482             :   {
     483             :     CSA_ASSERT(this, Word32BinaryNot(
     484             :                          HasInstanceType(p->receiver, JS_GLOBAL_OBJECT_TYPE)));
     485        2046 :     Node* properties = LoadSlowProperties(p->receiver);
     486         682 :     VARIABLE(var_name_index, MachineType::PointerRepresentation());
     487         682 :     Label found(this, &var_name_index);
     488             :     NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
     489         682 :                                          &var_name_index, &check_prototypes);
     490         682 :     BIND(&found);
     491             :     {
     492         682 :       VARIABLE(var_details, MachineRepresentation::kWord32);
     493        1364 :       VARIABLE(var_value, MachineRepresentation::kTagged);
     494             :       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
     495         682 :                                      &var_details, &var_value);
     496             :       Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
     497         682 :                                          p->context, p->receiver, miss);
     498        1364 :       exit_point->Return(value);
     499         682 :     }
     500             :   }
     501             : 
     502         682 :   BIND(&check_prototypes);
     503             :   Node* maybe_holder_cell =
     504             :       LoadObjectField(handler, LoadHandler::kHolderCellOffset);
     505         682 :   Label array_handler(this), tuple_handler(this);
     506        1364 :   Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler);
     507             : 
     508         682 :   BIND(&tuple_handler);
     509             :   {
     510         682 :     Label load_from_cached_holder(this), done(this);
     511             : 
     512        1364 :     Branch(WordEqual(maybe_holder_cell, NullConstant()), &done,
     513         682 :            &load_from_cached_holder);
     514             : 
     515         682 :     BIND(&load_from_cached_holder);
     516             :     {
     517             :       // For regular holders, having passed the receiver map check and the
     518             :       // validity cell check implies that |holder| is alive. However, for
     519             :       // global object receivers, the |maybe_holder_cell| may be cleared.
     520         682 :       Node* holder = LoadWeakCellValue(maybe_holder_cell, miss);
     521             : 
     522         682 :       var_holder->Bind(holder);
     523         682 :       Goto(&done);
     524             :     }
     525             : 
     526         682 :     BIND(&done);
     527         682 :     var_smi_handler->Bind(smi_handler);
     528        1364 :     Goto(if_smi_handler);
     529             :   }
     530             : 
     531         682 :   BIND(&array_handler);
     532             :   {
     533             :     exit_point->ReturnCallStub(
     534             :         CodeFactory::LoadICProtoArray(isolate(),
     535             :                                       throw_reference_error_if_nonexistent),
     536        1364 :         p->context, p->receiver, p->name, p->slot, p->vector, handler);
     537         682 :   }
     538         682 : }
     539             : 
     540         217 : void AccessorAssembler::EmitAccessCheck(Node* expected_native_context,
     541             :                                         Node* context, Node* receiver,
     542             :                                         Label* can_access, Label* miss) {
     543             :   CSA_ASSERT(this, IsNativeContext(expected_native_context));
     544             : 
     545         434 :   Node* native_context = LoadNativeContext(context);
     546         434 :   GotoIf(WordEqual(expected_native_context, native_context), can_access);
     547             :   // If the receiver is not a JSGlobalProxy then we miss.
     548         434 :   GotoIfNot(IsJSGlobalProxy(receiver), miss);
     549             :   // For JSGlobalProxy receiver try to compare security tokens of current
     550             :   // and expected native contexts.
     551             :   Node* expected_token = LoadContextElement(expected_native_context,
     552         434 :                                             Context::SECURITY_TOKEN_INDEX);
     553             :   Node* current_token =
     554         434 :       LoadContextElement(native_context, Context::SECURITY_TOKEN_INDEX);
     555         434 :   Branch(WordEqual(expected_token, current_token), can_access, miss);
     556         217 : }
     557             : 
     558          62 : Node* AccessorAssembler::EmitLoadICProtoArrayCheck(const LoadICParameters* p,
     559             :                                                    Node* handler,
     560             :                                                    Node* handler_length,
     561             :                                                    Node* handler_flags,
     562             :                                                    Label* miss) {
     563         124 :   VARIABLE(var_start_index, MachineType::PointerRepresentation(),
     564             :            IntPtrConstant(LoadHandler::kFirstPrototypeIndex));
     565             : 
     566          62 :   Label can_access(this);
     567             :   GotoIfNot(IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_flags),
     568         124 :             &can_access);
     569             :   {
     570             :     // Skip this entry of a handler.
     571         124 :     var_start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex + 1));
     572             : 
     573             :     int offset =
     574             :         FixedArray::OffsetOfElementAt(LoadHandler::kFirstPrototypeIndex);
     575             :     Node* expected_native_context =
     576          62 :         LoadWeakCellValue(LoadObjectField(handler, offset), miss);
     577             : 
     578             :     EmitAccessCheck(expected_native_context, p->context, p->receiver,
     579          62 :                     &can_access, miss);
     580             :   }
     581          62 :   BIND(&can_access);
     582             : 
     583             :   BuildFastLoop(var_start_index.value(), handler_length,
     584          62 :                 [=](Node* current) {
     585             :                   Node* prototype_cell =
     586          62 :                       LoadFixedArrayElement(handler, current);
     587          62 :                   CheckPrototype(prototype_cell, p->name, miss);
     588          62 :                 },
     589         124 :                 1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     590             : 
     591             :   Node* maybe_holder_cell =
     592          62 :       LoadFixedArrayElement(handler, LoadHandler::kHolderCellIndex);
     593             : 
     594         124 :   VARIABLE(var_holder, MachineRepresentation::kTagged, p->receiver);
     595          62 :   Label done(this);
     596         124 :   GotoIf(WordEqual(maybe_holder_cell, NullConstant()), &done);
     597             : 
     598             :   {
     599             :     // For regular holders, having passed the receiver map check and the
     600             :     // validity cell check implies that |holder| is alive. However, for
     601             :     // global object receivers, the |maybe_holder_cell| may be cleared.
     602          62 :     var_holder.Bind(LoadWeakCellValue(maybe_holder_cell, miss));
     603          62 :     Goto(&done);
     604             :   }
     605             : 
     606          62 :   BIND(&done);
     607         124 :   return var_holder.value();
     608             : }
     609             : 
     610         434 : void AccessorAssembler::HandleLoadGlobalICHandlerCase(
     611             :     const LoadICParameters* pp, Node* handler, Label* miss,
     612             :     ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) {
     613         434 :   LoadICParameters p = *pp;
     614             :   DCHECK_NULL(p.receiver);
     615        1302 :   Node* native_context = LoadNativeContext(p.context);
     616         868 :   p.receiver = LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
     617             : 
     618         868 :   VARIABLE(var_holder, MachineRepresentation::kTagged,
     619             :            LoadContextElement(native_context, Context::EXTENSION_INDEX));
     620         868 :   VARIABLE(var_smi_handler, MachineRepresentation::kTagged);
     621         434 :   Label if_smi_handler(this);
     622             : 
     623             :   HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler,
     624             :                                &if_smi_handler, miss, exit_point,
     625         434 :                                throw_reference_error_if_nonexistent);
     626         434 :   BIND(&if_smi_handler);
     627             :   HandleLoadICSmiHandlerCase(
     628             :       &p, var_holder.value(), var_smi_handler.value(), miss, exit_point,
     629         868 :       throw_reference_error_if_nonexistent, kOnlyProperties);
     630         434 : }
     631             : 
     632         310 : void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
     633             :                                            Label* readonly) {
     634             :   // Accessor properties never have the READ_ONLY attribute set.
     635         620 :   GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
     636         620 :          readonly);
     637             :   Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
     638         930 :   GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
     639             :   // Fall through if it's an accessor property.
     640         310 : }
     641             : 
     642         155 : void AccessorAssembler::HandleStoreICHandlerCase(
     643             :     const StoreICParameters* p, Node* handler, Label* miss,
     644             :     ElementSupport support_elements) {
     645         310 :   Label if_smi_handler(this), if_nonsmi_handler(this);
     646         155 :   Label if_proto_handler(this), if_element_handler(this), call_handler(this),
     647         155 :       store_global(this);
     648             : 
     649         310 :   Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler);
     650             : 
     651             :   // |handler| is a Smi, encoding what to do. See SmiHandler methods
     652             :   // for the encoding format.
     653         155 :   BIND(&if_smi_handler);
     654             :   {
     655         155 :     Node* holder = p->receiver;
     656         310 :     Node* handler_word = SmiUntag(handler);
     657             : 
     658         155 :     Label if_fast_smi(this), if_proxy(this);
     659             : 
     660             :     STATIC_ASSERT(StoreHandler::kStoreGlobalProxy + 1 ==
     661             :                   StoreHandler::kStoreNormal);
     662             :     STATIC_ASSERT(StoreHandler::kStoreNormal + 1 == StoreHandler::kProxy);
     663             :     STATIC_ASSERT(StoreHandler::kProxy + 1 == StoreHandler::kKindsNumber);
     664             : 
     665             :     Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
     666             :     GotoIf(IntPtrLessThan(handler_kind,
     667         310 :                           IntPtrConstant(StoreHandler::kStoreGlobalProxy)),
     668         310 :            &if_fast_smi);
     669         310 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)),
     670         310 :            &if_proxy);
     671             :     CSA_ASSERT(this, WordEqual(handler_kind,
     672             :                                IntPtrConstant(StoreHandler::kStoreNormal)));
     673         310 :     Node* properties = LoadSlowProperties(holder);
     674             : 
     675         310 :     VARIABLE(var_name_index, MachineType::PointerRepresentation());
     676         155 :     Label dictionary_found(this, &var_name_index);
     677             :     NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
     678         155 :                                          &var_name_index, miss);
     679         155 :     BIND(&dictionary_found);
     680             :     {
     681             :       Node* details = LoadDetailsByKeyIndex<NameDictionary>(
     682         155 :           properties, var_name_index.value());
     683             :       // Check that the property is a writable data property (no accessor).
     684             :       const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
     685             :                                        PropertyDetails::kAttributesReadOnlyMask;
     686             :       STATIC_ASSERT(kData == 0);
     687         310 :       GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
     688             : 
     689             :       StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
     690         155 :                                            p->value);
     691         310 :       Return(p->value);
     692             :     }
     693             : 
     694         155 :     BIND(&if_fast_smi);
     695             :     // Handle non-transitioning field stores.
     696         155 :     HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss);
     697             : 
     698         155 :     BIND(&if_proxy);
     699         310 :     HandleStoreToProxy(p, holder, miss, support_elements);
     700             :   }
     701             : 
     702         155 :   BIND(&if_nonsmi_handler);
     703             :   {
     704         310 :     Node* handler_map = LoadMap(handler);
     705         155 :     if (support_elements == kSupportElements) {
     706          62 :       GotoIf(IsTuple2Map(handler_map), &if_element_handler);
     707             :     }
     708         310 :     GotoIf(IsWeakCellMap(handler_map), &store_global);
     709         310 :     Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
     710             :   }
     711             : 
     712         155 :   if (support_elements == kSupportElements) {
     713          31 :     BIND(&if_element_handler);
     714          31 :     HandleStoreICElementHandlerCase(p, handler, miss);
     715             :   }
     716             : 
     717         155 :   BIND(&if_proto_handler);
     718         155 :   HandleStoreICProtoHandler(p, handler, miss, support_elements);
     719             : 
     720             :   // |handler| is a heap object. Must be code, call it.
     721         155 :   BIND(&call_handler);
     722             :   {
     723         155 :     StoreWithVectorDescriptor descriptor(isolate());
     724             :     TailCallStub(descriptor, handler, p->context, p->receiver, p->name,
     725         155 :                  p->value, p->slot, p->vector);
     726             :   }
     727             : 
     728         155 :   BIND(&store_global);
     729             :   {
     730             :     // Load value or miss if the {handler} weak cell is cleared.
     731         155 :     Node* cell = LoadWeakCellValue(handler, miss);
     732             : 
     733             :     ExitPoint direct_exit(this);
     734         155 :     StoreGlobalIC_PropertyCellCase(cell, p->value, &direct_exit, miss);
     735         155 :   }
     736         155 : }
     737             : 
     738          31 : void AccessorAssembler::HandleStoreICElementHandlerCase(
     739             :     const StoreICParameters* p, Node* handler, Label* miss) {
     740          31 :   Comment("HandleStoreICElementHandlerCase");
     741          31 :   Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset);
     742             :   Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
     743          62 :   GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
     744          31 :          miss);
     745             : 
     746             :   Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset);
     747             :   CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler)));
     748             : 
     749          31 :   StoreWithVectorDescriptor descriptor(isolate());
     750             :   TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name,
     751          31 :                p->value, p->slot, p->vector);
     752          31 : }
     753             : 
     754         155 : void AccessorAssembler::HandleStoreICProtoHandler(
     755             :     const StoreICParameters* p, Node* handler, Label* miss,
     756             :     ElementSupport support_elements) {
     757         155 :   Comment("HandleStoreICProtoHandler");
     758             : 
     759             :   // IC dispatchers rely on these assumptions to be held.
     760             :   STATIC_ASSERT(FixedArray::kLengthOffset ==
     761             :                 StoreHandler::kTransitionOrHolderCellOffset);
     762             :   DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex),
     763             :             StoreHandler::kSmiHandlerOffset);
     764             :   DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex),
     765             :             StoreHandler::kValidityCellOffset);
     766             : 
     767             :   // Both FixedArray and Tuple3 handlers have validity cell at the same offset.
     768             :   Label validity_cell_check_done(this);
     769             :   Node* validity_cell =
     770         155 :       LoadObjectField(handler, StoreHandler::kValidityCellOffset);
     771         310 :   GotoIf(WordEqual(validity_cell, IntPtrConstant(0)),
     772         310 :          &validity_cell_check_done);
     773             :   Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset);
     774         310 :   GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)),
     775         155 :          miss);
     776         155 :   Goto(&validity_cell_check_done);
     777             : 
     778         155 :   BIND(&validity_cell_check_done);
     779             :   Node* smi_or_code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
     780             : 
     781             :   Node* maybe_transition_cell =
     782             :       LoadObjectField(handler, StoreHandler::kTransitionOrHolderCellOffset);
     783         155 :   Label array_handler(this), tuple_handler(this);
     784         310 :   Branch(TaggedIsSmi(maybe_transition_cell), &array_handler, &tuple_handler);
     785             : 
     786         310 :   VARIABLE(var_transition_map_or_holder, MachineRepresentation::kTagged);
     787         155 :   Label do_store(this), if_transition_map(this), if_holder_object(this);
     788         155 :   BIND(&tuple_handler);
     789             :   {
     790         155 :     Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
     791         155 :     var_transition_map_or_holder.Bind(transition);
     792         155 :     Goto(&do_store);
     793             :   }
     794             : 
     795         155 :   BIND(&array_handler);
     796             :   {
     797         310 :     VARIABLE(var_start_index, MachineType::PointerRepresentation(),
     798             :              IntPtrConstant(StoreHandler::kFirstPrototypeIndex));
     799             : 
     800         155 :     Comment("array_handler");
     801         155 :     Label can_access(this);
     802             :     // Only Tuple3 handlers are allowed to have code handlers.
     803             :     CSA_ASSERT(this, TaggedIsSmi(smi_or_code));
     804             :     GotoIfNot(
     805             :         IsSetSmi(smi_or_code, StoreHandler::DoAccessCheckOnReceiverBits::kMask),
     806         310 :         &can_access);
     807             : 
     808             :     {
     809             :       // Skip this entry of a handler.
     810             :       var_start_index.Bind(
     811         310 :           IntPtrConstant(StoreHandler::kFirstPrototypeIndex + 1));
     812             : 
     813             :       int offset =
     814             :           FixedArray::OffsetOfElementAt(StoreHandler::kFirstPrototypeIndex);
     815             :       Node* expected_native_context =
     816         155 :           LoadWeakCellValue(LoadObjectField(handler, offset), miss);
     817             : 
     818             :       EmitAccessCheck(expected_native_context, p->context, p->receiver,
     819         155 :                       &can_access, miss);
     820             :     }
     821         155 :     BIND(&can_access);
     822             : 
     823         310 :     Node* length = SmiUntag(maybe_transition_cell);
     824             :     BuildFastLoop(var_start_index.value(), length,
     825         155 :                   [=](Node* current) {
     826             :                     Node* prototype_cell =
     827         155 :                         LoadFixedArrayElement(handler, current);
     828         155 :                     CheckPrototype(prototype_cell, p->name, miss);
     829         155 :                   },
     830         310 :                   1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     831             : 
     832             :     Node* maybe_transition_cell = LoadFixedArrayElement(
     833         155 :         handler, StoreHandler::kTransitionMapOrHolderCellIndex);
     834         155 :     Node* transition = LoadWeakCellValue(maybe_transition_cell, miss);
     835         155 :     var_transition_map_or_holder.Bind(transition);
     836         310 :     Goto(&do_store);
     837             :   }
     838             : 
     839         155 :   BIND(&do_store);
     840             :   {
     841         155 :     Node* transition = var_transition_map_or_holder.value();
     842         310 :     Branch(IsMap(transition), &if_transition_map, &if_holder_object);
     843             :   }
     844             : 
     845         155 :   BIND(&if_transition_map);
     846             :   {
     847         155 :     Label if_transition_to_constant(this), if_store_normal(this);
     848             : 
     849         155 :     Node* holder = p->receiver;
     850         155 :     Node* transition_map = var_transition_map_or_holder.value();
     851             : 
     852         310 :     GotoIf(IsDeprecatedMap(transition_map), miss);
     853             : 
     854         155 :     if (support_elements == kSupportElements) {
     855             :       Label if_smi_handler(this);
     856             : 
     857          62 :       GotoIf(TaggedIsSmi(smi_or_code), &if_smi_handler);
     858             :       Node* code_handler = smi_or_code;
     859             :       CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler)));
     860             : 
     861          31 :       StoreTransitionDescriptor descriptor(isolate());
     862             :       TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name,
     863          31 :                    transition_map, p->value, p->slot, p->vector);
     864             : 
     865          62 :       BIND(&if_smi_handler);
     866             :     }
     867             : 
     868             :     Node* smi_handler = smi_or_code;
     869             :     CSA_ASSERT(this, TaggedIsSmi(smi_handler));
     870         310 :     Node* handler_word = SmiUntag(smi_handler);
     871             : 
     872             :     Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
     873         310 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)),
     874         310 :            &if_store_normal);
     875             :     GotoIf(WordEqual(handler_kind,
     876         310 :                      IntPtrConstant(StoreHandler::kTransitionToConstant)),
     877         310 :            &if_transition_to_constant);
     878             :     CSA_ASSERT(this,
     879             :                WordEqual(handler_kind,
     880             :                          IntPtrConstant(StoreHandler::kTransitionToField)));
     881             : 
     882             :     // Handle transitioning field stores.
     883             :     HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition_map,
     884         155 :                                 miss);
     885             : 
     886         155 :     BIND(&if_transition_to_constant);
     887             :     {
     888             :       // Check that constant matches value.
     889             :       Node* descriptor = DecodeWord<StoreHandler::DescriptorBits>(handler_word);
     890             :       Node* scaled_descriptor =
     891         465 :           IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
     892             :       Node* value_index =
     893             :           IntPtrAdd(scaled_descriptor,
     894             :                     IntPtrConstant(DescriptorArray::kFirstIndex +
     895         465 :                                    DescriptorArray::kEntryValueIndex));
     896         310 :       Node* descriptors = LoadMapDescriptors(transition_map);
     897             :       CSA_ASSERT(
     898             :           this, UintPtrLessThan(descriptor,
     899             :                                 LoadAndUntagFixedArrayBaseLength(descriptors)));
     900             : 
     901         155 :       Node* constant = LoadFixedArrayElement(descriptors, value_index);
     902         465 :       GotoIf(WordNotEqual(p->value, constant), miss);
     903             : 
     904         155 :       StoreMap(p->receiver, transition_map);
     905         310 :       Return(p->value);
     906             :     }
     907             : 
     908         155 :     BIND(&if_store_normal);
     909             :     {
     910         465 :       Node* properties = LoadSlowProperties(p->receiver);
     911             : 
     912         155 :       VARIABLE(var_name_index, MachineType::PointerRepresentation());
     913         155 :       Label found(this, &var_name_index), not_found(this);
     914             :       NameDictionaryLookup<NameDictionary>(properties, p->name, &found,
     915         155 :                                            &var_name_index, &not_found);
     916         155 :       BIND(&found);
     917             :       {
     918             :         Node* details = LoadDetailsByKeyIndex<NameDictionary>(
     919         155 :             properties, var_name_index.value());
     920             :         // Check that the property is a writable data property (no accessor).
     921             :         const int kTypeAndReadOnlyMask =
     922             :             PropertyDetails::KindField::kMask |
     923             :             PropertyDetails::kAttributesReadOnlyMask;
     924             :         STATIC_ASSERT(kData == 0);
     925         310 :         GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
     926             : 
     927             :         StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
     928         155 :                                              p->value);
     929         310 :         Return(p->value);
     930             :       }
     931             : 
     932         155 :       BIND(&not_found);
     933             :       {
     934             :         Label slow(this);
     935         155 :         Add<NameDictionary>(properties, p->name, p->value, &slow);
     936         310 :         Return(p->value);
     937             : 
     938         155 :         BIND(&slow);
     939             :         TailCallRuntime(Runtime::kAddDictionaryProperty, p->context,
     940         310 :                         p->receiver, p->name, p->value);
     941         155 :       }
     942         155 :     }
     943             :   }
     944         155 :   BIND(&if_holder_object);
     945             :   {
     946             :     Label if_store_global_proxy(this);
     947         155 :     Node* holder = var_transition_map_or_holder.value();
     948             : 
     949             :     Node* smi_handler = smi_or_code;
     950             :     CSA_ASSERT(this, TaggedIsSmi(smi_handler));
     951         310 :     Node* handler_word = SmiUntag(smi_handler);
     952             : 
     953             :     Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
     954             :     GotoIf(WordEqual(handler_kind,
     955         310 :                      IntPtrConstant(StoreHandler::kStoreGlobalProxy)),
     956         310 :            &if_store_global_proxy);
     957             :     CSA_ASSERT(this,
     958             :                WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)));
     959         155 :     HandleStoreToProxy(p, holder, miss, support_elements);
     960             : 
     961         155 :     BIND(&if_store_global_proxy);
     962             :     {
     963             :       ExitPoint direct_exit(this);
     964         155 :       StoreGlobalIC_PropertyCellCase(holder, p->value, &direct_exit, miss);
     965         155 :     }
     966         155 :   }
     967         155 : }
     968             : 
     969         310 : void AccessorAssembler::HandleStoreToProxy(const StoreICParameters* p,
     970             :                                            Node* proxy, Label* miss,
     971             :                                            ElementSupport support_elements) {
     972         310 :   VARIABLE(var_index, MachineType::PointerRepresentation());
     973         620 :   VARIABLE(var_unique, MachineRepresentation::kTagged);
     974         930 :   VARIABLE(var_language_mode, MachineRepresentation::kTaggedSigned,
     975             :            SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
     976             : 
     977         310 :   Label if_index(this), if_unique_name(this), language_mode_determined(this),
     978         310 :       to_name_failed(this, Label::kDeferred);
     979         310 :   BranchIfStrictMode(p->vector, p->slot, &language_mode_determined);
     980         620 :   var_language_mode.Bind(SmiConstant(Smi::FromEnum(LanguageMode::kSloppy)));
     981         310 :   Goto(&language_mode_determined);
     982         310 :   BIND(&language_mode_determined);
     983             : 
     984         310 :   if (support_elements == kSupportElements) {
     985             :     TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
     986          62 :               &to_name_failed);
     987             : 
     988          62 :     BIND(&if_unique_name);
     989             :     CallBuiltin(Builtins::kProxySetProperty, p->context, proxy,
     990             :                 var_unique.value(), p->value, p->receiver,
     991          62 :                 var_language_mode.value());
     992         124 :     Return(p->value);
     993             : 
     994             :     // The index case is handled earlier by the runtime.
     995          62 :     BIND(&if_index);
     996             :     // TODO(mslekova): introduce TryToName that doesn't try to compute
     997             :     // the intptr index value
     998          62 :     Goto(&to_name_failed);
     999             : 
    1000          62 :     BIND(&to_name_failed);
    1001             :     TailCallRuntime(Runtime::kSetPropertyWithReceiver, p->context, proxy,
    1002          62 :                     p->name, p->value, p->receiver, var_language_mode.value());
    1003             :   } else {
    1004         248 :     Node* name = ToName(p->context, p->name);
    1005             :     TailCallBuiltin(Builtins::kProxySetProperty, p->context, proxy, name,
    1006         248 :                     p->value, p->receiver, var_language_mode.value());
    1007         310 :   }
    1008         310 : }
    1009             : 
    1010         310 : void AccessorAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
    1011             :                                                     Node* holder, Node* value,
    1012             :                                                     Node* transition,
    1013             :                                                     Label* miss) {
    1014         310 :   Comment(transition ? "transitioning field store" : "field store");
    1015             : 
    1016             : #ifdef DEBUG
    1017             :   Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
    1018             :   if (transition) {
    1019             :     CSA_ASSERT(
    1020             :         this,
    1021             :         Word32Or(
    1022             :             WordEqual(handler_kind,
    1023             :                       IntPtrConstant(StoreHandler::kTransitionToField)),
    1024             :             WordEqual(handler_kind,
    1025             :                       IntPtrConstant(StoreHandler::kTransitionToConstant))));
    1026             :   } else {
    1027             :     if (FLAG_track_constant_fields) {
    1028             :       CSA_ASSERT(
    1029             :           this,
    1030             :           Word32Or(WordEqual(handler_kind,
    1031             :                              IntPtrConstant(StoreHandler::kStoreField)),
    1032             :                    WordEqual(handler_kind,
    1033             :                              IntPtrConstant(StoreHandler::kStoreConstField))));
    1034             :     } else {
    1035             :       CSA_ASSERT(this, WordEqual(handler_kind,
    1036             :                                  IntPtrConstant(StoreHandler::kStoreField)));
    1037             :     }
    1038             :   }
    1039             : #endif
    1040             : 
    1041             :   Node* field_representation =
    1042         310 :       DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
    1043             : 
    1044         310 :   Label if_smi_field(this), if_double_field(this), if_heap_object_field(this),
    1045         310 :       if_tagged_field(this);
    1046             : 
    1047         620 :   GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)),
    1048         620 :          &if_tagged_field);
    1049             :   GotoIf(WordEqual(field_representation,
    1050         620 :                    IntPtrConstant(StoreHandler::kHeapObject)),
    1051         620 :          &if_heap_object_field);
    1052         620 :   GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)),
    1053         620 :          &if_double_field);
    1054             :   CSA_ASSERT(this, WordEqual(field_representation,
    1055             :                              IntPtrConstant(StoreHandler::kSmi)));
    1056         310 :   Goto(&if_smi_field);
    1057             : 
    1058         310 :   BIND(&if_tagged_field);
    1059             :   {
    1060         310 :     Comment("store tagged field");
    1061             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
    1062         310 :                               value, transition, miss);
    1063             :   }
    1064             : 
    1065         310 :   BIND(&if_double_field);
    1066             :   {
    1067         310 :     Comment("store double field");
    1068             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
    1069         310 :                               value, transition, miss);
    1070             :   }
    1071             : 
    1072         310 :   BIND(&if_heap_object_field);
    1073             :   {
    1074         310 :     Comment("store heap object field");
    1075             :     HandleStoreFieldAndReturn(handler_word, holder,
    1076             :                               Representation::HeapObject(), value, transition,
    1077         310 :                               miss);
    1078             :   }
    1079             : 
    1080         310 :   BIND(&if_smi_field);
    1081             :   {
    1082         310 :     Comment("store smi field");
    1083             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
    1084         310 :                               value, transition, miss);
    1085         310 :   }
    1086         310 : }
    1087             : 
    1088        1240 : void AccessorAssembler::HandleStoreFieldAndReturn(Node* handler_word,
    1089             :                                                   Node* holder,
    1090             :                                                   Representation representation,
    1091             :                                                   Node* value, Node* transition,
    1092             :                                                   Label* miss) {
    1093        1240 :   bool transition_to_field = transition != nullptr;
    1094             :   Node* prepared_value = PrepareValueForStore(
    1095        1240 :       handler_word, holder, representation, transition, value, miss);
    1096             : 
    1097        2480 :   Label if_inobject(this), if_out_of_object(this);
    1098             :   Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
    1099        2480 :          &if_out_of_object);
    1100             : 
    1101        1240 :   BIND(&if_inobject);
    1102             :   {
    1103             :     StoreNamedField(handler_word, holder, true, representation, prepared_value,
    1104        1240 :                     transition_to_field, miss);
    1105        1240 :     if (transition_to_field) {
    1106         620 :       StoreMap(holder, transition);
    1107             :     }
    1108        1240 :     Return(value);
    1109             :   }
    1110             : 
    1111        1240 :   BIND(&if_out_of_object);
    1112             :   {
    1113        1240 :     if (transition_to_field) {
    1114         620 :       ExtendPropertiesBackingStore(holder, handler_word);
    1115             :     }
    1116             : 
    1117             :     StoreNamedField(handler_word, holder, false, representation, prepared_value,
    1118        1240 :                     transition_to_field, miss);
    1119        1240 :     if (transition_to_field) {
    1120         620 :       StoreMap(holder, transition);
    1121             :     }
    1122        1240 :     Return(value);
    1123        1240 :   }
    1124        1240 : }
    1125             : 
    1126        1240 : Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder,
    1127             :                                               Representation representation,
    1128             :                                               Node* transition, Node* value,
    1129             :                                               Label* bailout) {
    1130        1240 :   if (representation.IsDouble()) {
    1131         310 :     value = TryTaggedToFloat64(value, bailout);
    1132             : 
    1133         930 :   } else if (representation.IsHeapObject()) {
    1134         620 :     GotoIf(TaggedIsSmi(value), bailout);
    1135             : 
    1136             :     Label done(this);
    1137             :     if (FLAG_track_constant_fields && !transition) {
    1138             :       // Skip field type check in favor of constant value check when storing
    1139             :       // to constant field.
    1140             :       GotoIf(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
    1141             :                        IntPtrConstant(StoreHandler::kStoreConstField)),
    1142             :              &done);
    1143             :     }
    1144             :     Node* descriptor = DecodeWord<StoreHandler::DescriptorBits>(handler_word);
    1145             :     Node* scaled_descriptor =
    1146         930 :         IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize));
    1147             :     Node* value_index =
    1148             :         IntPtrAdd(scaled_descriptor,
    1149             :                   IntPtrConstant(DescriptorArray::kFirstIndex +
    1150         930 :                                  DescriptorArray::kEntryValueIndex));
    1151             :     Node* descriptors =
    1152        1085 :         LoadMapDescriptors(transition ? transition : LoadMap(holder));
    1153             :     CSA_ASSERT(this,
    1154             :                UintPtrLessThan(descriptor,
    1155             :                                LoadAndUntagFixedArrayBaseLength(descriptors)));
    1156         310 :     Node* maybe_field_type = LoadFixedArrayElement(descriptors, value_index);
    1157             : 
    1158         620 :     GotoIf(TaggedIsSmi(maybe_field_type), &done);
    1159             :     // Check that value type matches the field type.
    1160             :     {
    1161         310 :       Node* field_type = LoadWeakCellValue(maybe_field_type, bailout);
    1162         620 :       Branch(WordEqual(LoadMap(value), field_type), &done, bailout);
    1163             :     }
    1164         310 :     BIND(&done);
    1165             : 
    1166         620 :   } else if (representation.IsSmi()) {
    1167         620 :     GotoIfNot(TaggedIsSmi(value), bailout);
    1168             : 
    1169             :   } else {
    1170             :     DCHECK(representation.IsTagged());
    1171             :   }
    1172        1240 :   return value;
    1173             : }
    1174             : 
    1175         620 : void AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
    1176             :                                                      Node* handler_word) {
    1177         620 :   Label done(this);
    1178        1240 :   GotoIfNot(IsSetWord<StoreHandler::ExtendStorageBits>(handler_word), &done);
    1179         620 :   Comment("[ Extend storage");
    1180             : 
    1181             :   ParameterMode mode = OptimalParameterMode();
    1182             : 
    1183             :   // TODO(gsathya): Clean up the type conversions by creating smarter
    1184             :   // helpers that do the correct op based on the mode.
    1185        1240 :   VARIABLE(var_properties, MachineRepresentation::kTaggedPointer);
    1186        1240 :   VARIABLE(var_encoded_hash, MachineRepresentation::kWord32);
    1187        1240 :   VARIABLE(var_length, ParameterRepresentation(mode));
    1188             : 
    1189             :   Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
    1190         620 :   var_properties.Bind(properties);
    1191             : 
    1192         620 :   Label if_smi_hash(this), if_property_array(this), extend_store(this);
    1193        1240 :   Branch(TaggedIsSmi(properties), &if_smi_hash, &if_property_array);
    1194             : 
    1195         620 :   BIND(&if_smi_hash);
    1196             :   {
    1197        1240 :     Node* hash = SmiToWord32(properties);
    1198             :     Node* encoded_hash =
    1199        1860 :         Word32Shl(hash, Int32Constant(PropertyArray::HashField::kShift));
    1200         620 :     var_encoded_hash.Bind(encoded_hash);
    1201         620 :     var_length.Bind(IntPtrOrSmiConstant(0, mode));
    1202        1240 :     var_properties.Bind(EmptyFixedArrayConstant());
    1203         620 :     Goto(&extend_store);
    1204             :   }
    1205             : 
    1206         620 :   BIND(&if_property_array);
    1207             :   {
    1208             :     Node* length_and_hash_int32 = LoadAndUntagToWord32ObjectField(
    1209        1240 :         var_properties.value(), PropertyArray::kLengthAndHashOffset);
    1210             :     var_encoded_hash.Bind(Word32And(
    1211        1860 :         length_and_hash_int32, Int32Constant(PropertyArray::HashField::kMask)));
    1212             :     Node* length_intptr = ChangeInt32ToIntPtr(
    1213             :         Word32And(length_and_hash_int32,
    1214        2480 :                   Int32Constant(PropertyArray::LengthField::kMask)));
    1215             :     Node* length = WordToParameter(length_intptr, mode);
    1216         620 :     var_length.Bind(length);
    1217         620 :     Goto(&extend_store);
    1218             :   }
    1219             : 
    1220         620 :   BIND(&extend_store);
    1221             :   {
    1222             :     // Previous property deletion could have left behind unused backing store
    1223             :     // capacity even for a map that think it doesn't have any unused fields.
    1224             :     // Perform a bounds check to see if we actually have to grow the array.
    1225             :     Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
    1226             :     Node* size = ElementOffsetFromIndex(var_length.value(), PACKED_ELEMENTS,
    1227         620 :                                         mode, FixedArray::kHeaderSize);
    1228        1240 :     GotoIf(UintPtrLessThan(offset, size), &done);
    1229             : 
    1230         620 :     Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode);
    1231         620 :     Node* new_capacity = IntPtrOrSmiAdd(var_length.value(), delta, mode);
    1232             : 
    1233             :     // Grow properties array.
    1234             :     DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded <
    1235             :            FixedArrayBase::GetMaxLengthForNewSpaceAllocation(PACKED_ELEMENTS));
    1236             :     // The size of a new properties backing store is guaranteed to be small
    1237             :     // enough that the new backing store will be allocated in new space.
    1238             :     CSA_ASSERT(this,
    1239             :                UintPtrOrSmiLessThan(
    1240             :                    new_capacity,
    1241             :                    IntPtrOrSmiConstant(
    1242             :                        kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode),
    1243             :                    mode));
    1244             : 
    1245         620 :     Node* new_properties = AllocatePropertyArray(new_capacity, mode);
    1246             : 
    1247             :     FillPropertyArrayWithUndefined(new_properties, var_length.value(),
    1248         620 :                                    new_capacity, mode);
    1249             : 
    1250             :     // |new_properties| is guaranteed to be in new space, so we can skip
    1251             :     // the write barrier.
    1252             :     CopyPropertyArrayValues(var_properties.value(), new_properties,
    1253         620 :                             var_length.value(), SKIP_WRITE_BARRIER, mode);
    1254             : 
    1255             :     // TODO(gsathya): Clean up the type conversions by creating smarter
    1256             :     // helpers that do the correct op based on the mode.
    1257             :     Node* new_capacity_int32 =
    1258        1240 :         TruncateWordToWord32(ParameterToWord(new_capacity, mode));
    1259             :     Node* new_length_and_hash_int32 =
    1260        1860 :         Word32Or(var_encoded_hash.value(), new_capacity_int32);
    1261             :     StoreObjectField(new_properties, PropertyArray::kLengthAndHashOffset,
    1262        1240 :                      SmiFromWord32(new_length_and_hash_int32));
    1263         620 :     StoreObjectField(object, JSObject::kPropertiesOrHashOffset, new_properties);
    1264         620 :     Comment("] Extend storage");
    1265         620 :     Goto(&done);
    1266             :   }
    1267        1240 :   BIND(&done);
    1268         620 : }
    1269             : 
    1270        2480 : void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object,
    1271             :                                         bool is_inobject,
    1272             :                                         Representation representation,
    1273             :                                         Node* value, bool transition_to_field,
    1274             :                                         Label* bailout) {
    1275             :   bool store_value_as_double = representation.IsDouble();
    1276             :   Node* property_storage = object;
    1277        2480 :   if (!is_inobject) {
    1278        2480 :     property_storage = LoadFastProperties(object);
    1279             :   }
    1280             : 
    1281        2480 :   Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word);
    1282        2480 :   if (representation.IsDouble()) {
    1283         620 :     if (!FLAG_unbox_double_fields || !is_inobject) {
    1284         310 :       if (transition_to_field) {
    1285         310 :         Node* heap_number = AllocateHeapNumberWithValue(value, MUTABLE);
    1286             :         // Store the new mutable heap number into the object.
    1287             :         value = heap_number;
    1288             :         store_value_as_double = false;
    1289             :       } else {
    1290             :         // Load the heap number.
    1291             :         property_storage = LoadObjectField(property_storage, offset);
    1292             :         // Store the double value into it.
    1293         310 :         offset = IntPtrConstant(HeapNumber::kValueOffset);
    1294             :       }
    1295             :     }
    1296             :   }
    1297             : 
    1298             :   // Do constant value check if necessary.
    1299             :   if (FLAG_track_constant_fields && !transition_to_field) {
    1300             :     Label done(this);
    1301             :     GotoIfNot(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
    1302             :                         IntPtrConstant(StoreHandler::kStoreConstField)),
    1303             :               &done);
    1304             :     {
    1305             :       if (store_value_as_double) {
    1306             :         Node* current_value =
    1307             :             LoadObjectField(property_storage, offset, MachineType::Float64());
    1308             :         GotoIfNot(Float64Equal(current_value, value), bailout);
    1309             :       } else {
    1310             :         Node* current_value = LoadObjectField(property_storage, offset);
    1311             :         GotoIfNot(WordEqual(current_value, value), bailout);
    1312             :       }
    1313             :       Goto(&done);
    1314             :     }
    1315             :     BIND(&done);
    1316             :   }
    1317             : 
    1318             :   // Do the store.
    1319        2480 :   if (store_value_as_double) {
    1320             :     StoreObjectFieldNoWriteBarrier(property_storage, offset, value,
    1321         465 :                                    MachineRepresentation::kFloat64);
    1322        2015 :   } else if (representation.IsSmi()) {
    1323         620 :     StoreObjectFieldNoWriteBarrier(property_storage, offset, value);
    1324             :   } else {
    1325        1395 :     StoreObjectField(property_storage, offset, value);
    1326             :   }
    1327        2480 : }
    1328             : 
    1329          62 : void AccessorAssembler::EmitFastElementsBoundsCheck(Node* object,
    1330             :                                                     Node* elements,
    1331             :                                                     Node* intptr_index,
    1332             :                                                     Node* is_jsarray_condition,
    1333             :                                                     Label* miss) {
    1334          62 :   VARIABLE(var_length, MachineType::PointerRepresentation());
    1335          62 :   Comment("Fast elements bounds check");
    1336          62 :   Label if_array(this), length_loaded(this, &var_length);
    1337          62 :   GotoIf(is_jsarray_condition, &if_array);
    1338             :   {
    1339         186 :     var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
    1340          62 :     Goto(&length_loaded);
    1341             :   }
    1342          62 :   BIND(&if_array);
    1343             :   {
    1344         186 :     var_length.Bind(SmiUntag(LoadFastJSArrayLength(object)));
    1345          62 :     Goto(&length_loaded);
    1346             :   }
    1347          62 :   BIND(&length_loaded);
    1348         248 :   GotoIfNot(UintPtrLessThan(intptr_index, var_length.value()), miss);
    1349          62 : }
    1350             : 
    1351          62 : void AccessorAssembler::EmitElementLoad(
    1352             :     Node* object, Node* elements, Node* elements_kind, Node* intptr_index,
    1353             :     Node* is_jsarray_condition, Label* if_hole, Label* rebox_double,
    1354             :     Variable* var_double_value, Label* unimplemented_elements_kind,
    1355             :     Label* out_of_bounds, Label* miss, ExitPoint* exit_point) {
    1356         124 :   Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
    1357          62 :       if_fast_double(this), if_fast_holey_double(this), if_nonfast(this),
    1358          62 :       if_dictionary(this);
    1359             :   GotoIf(
    1360         124 :       Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
    1361         124 :       &if_nonfast);
    1362             : 
    1363             :   EmitFastElementsBoundsCheck(object, elements, intptr_index,
    1364          62 :                               is_jsarray_condition, out_of_bounds);
    1365             :   int32_t kinds[] = {// Handled by if_fast_packed.
    1366             :                      PACKED_SMI_ELEMENTS, PACKED_ELEMENTS,
    1367             :                      // Handled by if_fast_holey.
    1368             :                      HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS,
    1369             :                      // Handled by if_fast_double.
    1370             :                      PACKED_DOUBLE_ELEMENTS,
    1371             :                      // Handled by if_fast_holey_double.
    1372          62 :                      HOLEY_DOUBLE_ELEMENTS};
    1373             :   Label* labels[] = {// FAST_{SMI,}_ELEMENTS
    1374             :                      &if_fast_packed, &if_fast_packed,
    1375             :                      // FAST_HOLEY_{SMI,}_ELEMENTS
    1376             :                      &if_fast_holey, &if_fast_holey,
    1377             :                      // PACKED_DOUBLE_ELEMENTS
    1378             :                      &if_fast_double,
    1379             :                      // HOLEY_DOUBLE_ELEMENTS
    1380          62 :                      &if_fast_holey_double};
    1381             :   Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
    1382          62 :          arraysize(kinds));
    1383             : 
    1384          62 :   BIND(&if_fast_packed);
    1385             :   {
    1386          62 :     Comment("fast packed elements");
    1387          62 :     exit_point->Return(LoadFixedArrayElement(elements, intptr_index));
    1388             :   }
    1389             : 
    1390          62 :   BIND(&if_fast_holey);
    1391             :   {
    1392          62 :     Comment("fast holey elements");
    1393          62 :     Node* element = LoadFixedArrayElement(elements, intptr_index);
    1394         124 :     GotoIf(WordEqual(element, TheHoleConstant()), if_hole);
    1395          62 :     exit_point->Return(element);
    1396             :   }
    1397             : 
    1398          62 :   BIND(&if_fast_double);
    1399             :   {
    1400          62 :     Comment("packed double elements");
    1401             :     var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index,
    1402          62 :                                                        MachineType::Float64()));
    1403          62 :     Goto(rebox_double);
    1404             :   }
    1405             : 
    1406          62 :   BIND(&if_fast_holey_double);
    1407             :   {
    1408          62 :     Comment("holey double elements");
    1409             :     Node* value = LoadFixedDoubleArrayElement(elements, intptr_index,
    1410             :                                               MachineType::Float64(), 0,
    1411          62 :                                               INTPTR_PARAMETERS, if_hole);
    1412          62 :     var_double_value->Bind(value);
    1413          62 :     Goto(rebox_double);
    1414             :   }
    1415             : 
    1416          62 :   BIND(&if_nonfast);
    1417             :   {
    1418             :     STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
    1419             :     GotoIf(Int32GreaterThanOrEqual(
    1420             :                elements_kind,
    1421         124 :                Int32Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
    1422         124 :            &if_typed_array);
    1423         124 :     GotoIf(Word32Equal(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)),
    1424         124 :            &if_dictionary);
    1425          62 :     Goto(unimplemented_elements_kind);
    1426             :   }
    1427             : 
    1428          62 :   BIND(&if_dictionary);
    1429             :   {
    1430          62 :     Comment("dictionary elements");
    1431         186 :     GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds);
    1432          62 :     VARIABLE(var_entry, MachineType::PointerRepresentation());
    1433          62 :     Label if_found(this);
    1434             :     NumberDictionaryLookup<SeededNumberDictionary>(
    1435          62 :         elements, intptr_index, &if_found, &var_entry, if_hole);
    1436          62 :     BIND(&if_found);
    1437             :     // Check that the value is a data property.
    1438          62 :     Node* index = EntryToIndex<SeededNumberDictionary>(var_entry.value());
    1439             :     Node* details =
    1440             :         LoadDetailsByKeyIndex<SeededNumberDictionary>(elements, index);
    1441             :     Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
    1442             :     // TODO(jkummerow): Support accessors without missing?
    1443         186 :     GotoIfNot(Word32Equal(kind, Int32Constant(kData)), miss);
    1444             :     // Finally, load the value.
    1445             :     exit_point->Return(
    1446         124 :         LoadValueByKeyIndex<SeededNumberDictionary>(elements, index));
    1447             :   }
    1448             : 
    1449          62 :   BIND(&if_typed_array);
    1450             :   {
    1451          62 :     Comment("typed elements");
    1452             :     // Check if buffer has been neutered.
    1453             :     Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
    1454         124 :     GotoIf(IsDetachedBuffer(buffer), miss);
    1455             : 
    1456             :     // Bounds check.
    1457             :     Node* length =
    1458         124 :         SmiUntag(CAST(LoadObjectField(object, JSTypedArray::kLengthOffset)));
    1459         124 :     GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
    1460             : 
    1461             :     // Backing store = external_pointer + base_pointer.
    1462             :     Node* external_pointer =
    1463             :         LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
    1464          62 :                         MachineType::Pointer());
    1465             :     Node* base_pointer =
    1466             :         LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
    1467             :     Node* backing_store =
    1468         186 :         IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer));
    1469             : 
    1470          62 :     Label uint8_elements(this), int8_elements(this), uint16_elements(this),
    1471          62 :         int16_elements(this), uint32_elements(this), int32_elements(this),
    1472          62 :         float32_elements(this), float64_elements(this);
    1473             :     Label* elements_kind_labels[] = {
    1474             :         &uint8_elements,  &uint8_elements,   &int8_elements,
    1475             :         &uint16_elements, &int16_elements,   &uint32_elements,
    1476          62 :         &int32_elements,  &float32_elements, &float64_elements};
    1477             :     int32_t elements_kinds[] = {
    1478             :         UINT8_ELEMENTS,  UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
    1479             :         UINT16_ELEMENTS, INT16_ELEMENTS,         UINT32_ELEMENTS,
    1480          62 :         INT32_ELEMENTS,  FLOAT32_ELEMENTS,       FLOAT64_ELEMENTS};
    1481             :     const size_t kTypedElementsKindCount =
    1482             :         LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
    1483             :         FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
    1484             :     DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
    1485             :     DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
    1486             :     Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
    1487          62 :            kTypedElementsKindCount);
    1488          62 :     BIND(&uint8_elements);
    1489             :     {
    1490          62 :       Comment("UINT8_ELEMENTS");  // Handles UINT8_CLAMPED_ELEMENTS too.
    1491          62 :       Node* element = Load(MachineType::Uint8(), backing_store, intptr_index);
    1492         124 :       exit_point->Return(SmiFromWord32(element));
    1493             :     }
    1494          62 :     BIND(&int8_elements);
    1495             :     {
    1496          62 :       Comment("INT8_ELEMENTS");
    1497          62 :       Node* element = Load(MachineType::Int8(), backing_store, intptr_index);
    1498         124 :       exit_point->Return(SmiFromWord32(element));
    1499             :     }
    1500          62 :     BIND(&uint16_elements);
    1501             :     {
    1502          62 :       Comment("UINT16_ELEMENTS");
    1503         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(1));
    1504          62 :       Node* element = Load(MachineType::Uint16(), backing_store, index);
    1505         124 :       exit_point->Return(SmiFromWord32(element));
    1506             :     }
    1507          62 :     BIND(&int16_elements);
    1508             :     {
    1509          62 :       Comment("INT16_ELEMENTS");
    1510         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(1));
    1511          62 :       Node* element = Load(MachineType::Int16(), backing_store, index);
    1512         124 :       exit_point->Return(SmiFromWord32(element));
    1513             :     }
    1514          62 :     BIND(&uint32_elements);
    1515             :     {
    1516          62 :       Comment("UINT32_ELEMENTS");
    1517         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1518          62 :       Node* element = Load(MachineType::Uint32(), backing_store, index);
    1519         124 :       exit_point->Return(ChangeUint32ToTagged(element));
    1520             :     }
    1521          62 :     BIND(&int32_elements);
    1522             :     {
    1523          62 :       Comment("INT32_ELEMENTS");
    1524         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1525          62 :       Node* element = Load(MachineType::Int32(), backing_store, index);
    1526         124 :       exit_point->Return(ChangeInt32ToTagged(element));
    1527             :     }
    1528          62 :     BIND(&float32_elements);
    1529             :     {
    1530          62 :       Comment("FLOAT32_ELEMENTS");
    1531         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1532          62 :       Node* element = Load(MachineType::Float32(), backing_store, index);
    1533         124 :       var_double_value->Bind(ChangeFloat32ToFloat64(element));
    1534          62 :       Goto(rebox_double);
    1535             :     }
    1536          62 :     BIND(&float64_elements);
    1537             :     {
    1538          62 :       Comment("FLOAT64_ELEMENTS");
    1539         186 :       Node* index = WordShl(intptr_index, IntPtrConstant(3));
    1540          62 :       Node* element = Load(MachineType::Float64(), backing_store, index);
    1541          62 :       var_double_value->Bind(element);
    1542          62 :       Goto(rebox_double);
    1543          62 :     }
    1544          62 :   }
    1545          62 : }
    1546             : 
    1547         217 : void AccessorAssembler::CheckPrototype(Node* prototype_cell, Node* name,
    1548             :                                        Label* miss) {
    1549         217 :   Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss);
    1550             : 
    1551         217 :   Label done(this);
    1552         217 :   Label if_property_cell(this), if_dictionary_object(this);
    1553             : 
    1554             :   // |maybe_prototype| is either a PropertyCell or a slow-mode prototype.
    1555             :   Branch(IsPropertyCell(maybe_prototype), &if_property_cell,
    1556         434 :          &if_dictionary_object);
    1557             : 
    1558         217 :   BIND(&if_dictionary_object);
    1559             :   {
    1560             :     CSA_ASSERT(this, IsDictionaryMap(LoadMap(maybe_prototype)));
    1561         217 :     NameDictionaryNegativeLookup(maybe_prototype, name, miss);
    1562         217 :     Goto(&done);
    1563             :   }
    1564             : 
    1565         217 :   BIND(&if_property_cell);
    1566             :   {
    1567             :     // Ensure the property cell still contains the hole.
    1568             :     Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset);
    1569         434 :     GotoIfNot(IsTheHole(value), miss);
    1570         217 :     Goto(&done);
    1571             :   }
    1572             : 
    1573         434 :   BIND(&done);
    1574         217 : }
    1575             : 
    1576         217 : void AccessorAssembler::NameDictionaryNegativeLookup(Node* object, Node* name,
    1577             :                                                      Label* miss) {
    1578             :   CSA_ASSERT(this, IsDictionaryMap(LoadMap(object)));
    1579         434 :   Node* properties = LoadSlowProperties(object);
    1580             :   // Ensure the property does not exist in a dictionary-mode object.
    1581         217 :   VARIABLE(var_name_index, MachineType::PointerRepresentation());
    1582         217 :   Label done(this);
    1583             :   NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index,
    1584         217 :                                        &done);
    1585         434 :   BIND(&done);
    1586         217 : }
    1587             : 
    1588         465 : void AccessorAssembler::BranchIfStrictMode(Node* vector, Node* slot,
    1589             :                                            Label* if_strict) {
    1590             :   Node* sfi =
    1591         465 :       LoadObjectField(vector, FeedbackVector::kSharedFunctionInfoOffset);
    1592             :   Node* metadata =
    1593             :       LoadObjectField(sfi, SharedFunctionInfo::kFeedbackMetadataOffset);
    1594         930 :   Node* slot_int = SmiToWord32(slot);
    1595             : 
    1596             :   // See VectorICComputer::index().
    1597             :   const int kItemsPerWord = FeedbackMetadata::VectorICComputer::kItemsPerWord;
    1598        1395 :   Node* word_index = Int32Div(slot_int, Int32Constant(kItemsPerWord));
    1599        1395 :   Node* word_offset = Int32Mod(slot_int, Int32Constant(kItemsPerWord));
    1600             :   Node* data = SmiToWord32(LoadFixedArrayElement(
    1601         465 :       metadata, ChangeInt32ToIntPtr(word_index),
    1602        1860 :       FeedbackMetadata::kReservedIndexCount * kPointerSize, INTPTR_PARAMETERS));
    1603             :   // See VectorICComputer::decode().
    1604             :   const int kBitsPerItem = FeedbackMetadata::kFeedbackSlotKindBits;
    1605        1395 :   Node* shift = Int32Mul(word_offset, Int32Constant(kBitsPerItem));
    1606             :   const int kMask = FeedbackMetadata::VectorICComputer::kMask;
    1607        1860 :   Node* kind = Word32And(Word32Shr(data, shift), Int32Constant(kMask));
    1608             : 
    1609             :   STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
    1610             :                 FeedbackSlotKind::kLastSloppyKind);
    1611             :   STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
    1612             :                 FeedbackSlotKind::kLastSloppyKind);
    1613             :   STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
    1614             :                 FeedbackSlotKind::kLastSloppyKind);
    1615             :   GotoIfNot(Int32LessThanOrEqual(kind, Int32Constant(static_cast<int>(
    1616         930 :                                            FeedbackSlotKind::kLastSloppyKind))),
    1617         930 :             if_strict);
    1618         465 : }
    1619             : 
    1620          31 : void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
    1621             :                                            Node* instance_type, Node* index,
    1622             :                                            Label* slow) {
    1623          31 :   Comment("integer index");
    1624             : 
    1625          31 :   ExitPoint direct_exit(this);
    1626             : 
    1627          31 :   Label if_element_hole(this), if_oob(this);
    1628             :   // Receivers requiring non-standard element accesses (interceptors, access
    1629             :   // checks, strings and string wrappers, proxies) are handled in the runtime.
    1630             :   GotoIf(Int32LessThanOrEqual(instance_type,
    1631          62 :                               Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
    1632          62 :          slow);
    1633          62 :   Node* elements = LoadElements(receiver);
    1634          62 :   Node* elements_kind = LoadMapElementsKind(receiver_map);
    1635          31 :   Node* is_jsarray_condition = InstanceTypeEqual(instance_type, JS_ARRAY_TYPE);
    1636          62 :   VARIABLE(var_double_value, MachineRepresentation::kFloat64);
    1637          31 :   Label rebox_double(this, &var_double_value);
    1638             : 
    1639             :   // Unimplemented elements kinds fall back to a runtime call.
    1640             :   Label* unimplemented_elements_kind = slow;
    1641          62 :   IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
    1642             :   EmitElementLoad(receiver, elements, elements_kind, index,
    1643             :                   is_jsarray_condition, &if_element_hole, &rebox_double,
    1644             :                   &var_double_value, unimplemented_elements_kind, &if_oob, slow,
    1645          31 :                   &direct_exit);
    1646             : 
    1647          31 :   BIND(&rebox_double);
    1648          93 :   Return(AllocateHeapNumberWithValue(var_double_value.value()));
    1649             : 
    1650          31 :   BIND(&if_oob);
    1651             :   {
    1652          31 :     Comment("out of bounds");
    1653             :     // Negative keys can't take the fast OOB path.
    1654          93 :     GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow);
    1655             :     // Positive OOB indices are effectively the same as hole loads.
    1656          31 :     Goto(&if_element_hole);
    1657             :   }
    1658             : 
    1659          31 :   BIND(&if_element_hole);
    1660             :   {
    1661          31 :     Comment("found the hole");
    1662             :     Label return_undefined(this);
    1663          31 :     BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, slow);
    1664             : 
    1665          31 :     BIND(&return_undefined);
    1666          62 :     Return(UndefinedConstant());
    1667          31 :   }
    1668          31 : }
    1669             : 
    1670          62 : void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
    1671             :                                             Node* instance_type,
    1672             :                                             const LoadICParameters* p,
    1673             :                                             Label* slow,
    1674             :                                             UseStubCache use_stub_cache) {
    1675          62 :   ExitPoint direct_exit(this);
    1676             : 
    1677          62 :   Comment("key is unique name");
    1678          62 :   Label if_found_on_receiver(this), if_property_dictionary(this),
    1679          62 :       lookup_prototype_chain(this), special_receiver(this);
    1680         124 :   VARIABLE(var_details, MachineRepresentation::kWord32);
    1681         124 :   VARIABLE(var_value, MachineRepresentation::kTagged);
    1682             : 
    1683             :   // Receivers requiring non-standard accesses (interceptors, access
    1684             :   // checks, strings and string wrappers) are handled in the runtime.
    1685             :   GotoIf(Int32LessThanOrEqual(instance_type,
    1686         124 :                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
    1687         124 :          &special_receiver);
    1688             : 
    1689             :   // Check if the receiver has fast or slow properties.
    1690         124 :   Node* bitfield3 = LoadMapBitField3(receiver_map);
    1691          62 :   GotoIf(IsSetWord32<Map::DictionaryMap>(bitfield3), &if_property_dictionary);
    1692             : 
    1693             :   // Try looking up the property on the receiver; if unsuccessful, look
    1694             :   // for a handler in the stub cache.
    1695         124 :   Node* descriptors = LoadMapDescriptors(receiver_map);
    1696             : 
    1697          62 :   Label if_descriptor_found(this), stub_cache(this);
    1698         124 :   VARIABLE(var_name_index, MachineType::PointerRepresentation());
    1699             :   Label* notfound =
    1700          62 :       use_stub_cache == kUseStubCache ? &stub_cache : &lookup_prototype_chain;
    1701             :   DescriptorLookup(p->name, descriptors, bitfield3, &if_descriptor_found,
    1702          62 :                    &var_name_index, notfound);
    1703             : 
    1704          62 :   BIND(&if_descriptor_found);
    1705             :   {
    1706             :     LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
    1707             :                                var_name_index.value(), &var_details,
    1708          62 :                                &var_value);
    1709          62 :     Goto(&if_found_on_receiver);
    1710             :   }
    1711             : 
    1712          62 :   if (use_stub_cache == kUseStubCache) {
    1713          31 :     BIND(&stub_cache);
    1714          31 :     Comment("stub cache probe for fast property load");
    1715          31 :     VARIABLE(var_handler, MachineRepresentation::kTagged);
    1716          31 :     Label found_handler(this, &var_handler), stub_cache_miss(this);
    1717             :     TryProbeStubCache(isolate()->load_stub_cache(), receiver, p->name,
    1718          31 :                       &found_handler, &var_handler, &stub_cache_miss);
    1719          31 :     BIND(&found_handler);
    1720             :     {
    1721             :       HandleLoadICHandlerCase(p, var_handler.value(), &stub_cache_miss,
    1722          31 :                               &direct_exit);
    1723             :     }
    1724             : 
    1725          31 :     BIND(&stub_cache_miss);
    1726             :     {
    1727             :       // TODO(jkummerow): Check if the property exists on the prototype
    1728             :       // chain. If it doesn't, then there's no point in missing.
    1729          31 :       Comment("KeyedLoadGeneric_miss");
    1730             :       TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
    1731          31 :                       p->name, p->slot, p->vector);
    1732          31 :     }
    1733             :   }
    1734             : 
    1735          62 :   BIND(&if_property_dictionary);
    1736             :   {
    1737          62 :     Comment("dictionary property load");
    1738             :     // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
    1739             :     // seeing global objects here (which would need special handling).
    1740             : 
    1741          62 :     VARIABLE(var_name_index, MachineType::PointerRepresentation());
    1742          62 :     Label dictionary_found(this, &var_name_index);
    1743         124 :     Node* properties = LoadSlowProperties(receiver);
    1744             :     NameDictionaryLookup<NameDictionary>(properties, p->name, &dictionary_found,
    1745             :                                          &var_name_index,
    1746          62 :                                          &lookup_prototype_chain);
    1747          62 :     BIND(&dictionary_found);
    1748             :     {
    1749             :       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
    1750          62 :                                      &var_details, &var_value);
    1751          62 :       Goto(&if_found_on_receiver);
    1752          62 :     }
    1753             :   }
    1754             : 
    1755          62 :   BIND(&if_found_on_receiver);
    1756             :   {
    1757             :     Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
    1758          62 :                                        p->context, receiver, slow);
    1759         124 :     IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1);
    1760          62 :     Return(value);
    1761             :   }
    1762             : 
    1763          62 :   BIND(&lookup_prototype_chain);
    1764             :   {
    1765          62 :     VARIABLE(var_holder_map, MachineRepresentation::kTagged);
    1766         124 :     VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32);
    1767          62 :     Label return_undefined(this);
    1768          62 :     Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type};
    1769         124 :     Label loop(this, arraysize(merged_variables), merged_variables);
    1770             : 
    1771          62 :     var_holder_map.Bind(receiver_map);
    1772          62 :     var_holder_instance_type.Bind(instance_type);
    1773             :     // Private symbols must not be looked up on the prototype chain.
    1774         124 :     GotoIf(IsPrivateSymbol(p->name), &return_undefined);
    1775          62 :     Goto(&loop);
    1776          62 :     BIND(&loop);
    1777             :     {
    1778             :       // Bailout if it can be an integer indexed exotic case.
    1779             :       GotoIf(InstanceTypeEqual(var_holder_instance_type.value(),
    1780             :                                JS_TYPED_ARRAY_TYPE),
    1781         124 :              slow);
    1782         186 :       Node* proto = LoadMapPrototype(var_holder_map.value());
    1783         124 :       GotoIf(WordEqual(proto, NullConstant()), &return_undefined);
    1784         124 :       Node* proto_map = LoadMap(proto);
    1785         124 :       Node* proto_instance_type = LoadMapInstanceType(proto_map);
    1786          62 :       var_holder_map.Bind(proto_map);
    1787          62 :       var_holder_instance_type.Bind(proto_instance_type);
    1788          62 :       Label next_proto(this), return_value(this, &var_value), goto_slow(this);
    1789             :       TryGetOwnProperty(p->context, receiver, proto, proto_map,
    1790             :                         proto_instance_type, p->name, &return_value, &var_value,
    1791          62 :                         &next_proto, &goto_slow);
    1792             : 
    1793             :       // This trampoline and the next are required to appease Turbofan's
    1794             :       // variable merging.
    1795          62 :       BIND(&next_proto);
    1796          62 :       Goto(&loop);
    1797             : 
    1798          62 :       BIND(&goto_slow);
    1799          62 :       Goto(slow);
    1800             : 
    1801          62 :       BIND(&return_value);
    1802         186 :       Return(var_value.value());
    1803             :     }
    1804             : 
    1805          62 :     BIND(&return_undefined);
    1806         186 :     Return(UndefinedConstant());
    1807             :   }
    1808             : 
    1809          62 :   BIND(&special_receiver);
    1810             :   {
    1811             :     // TODO(jkummerow): Consider supporting JSModuleNamespace.
    1812         124 :     GotoIfNot(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), slow);
    1813             : 
    1814             :     direct_exit.ReturnCallStub(
    1815             :         Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
    1816             :         p->context, receiver /*holder is the same as receiver*/, p->name,
    1817         124 :         receiver);
    1818          62 :   }
    1819          62 : }
    1820             : 
    1821             : //////////////////// Stub cache access helpers.
    1822             : 
    1823             : enum AccessorAssembler::StubCacheTable : int {
    1824             :   kPrimary = static_cast<int>(StubCache::kPrimary),
    1825             :   kSecondary = static_cast<int>(StubCache::kSecondary)
    1826             : };
    1827             : 
    1828         173 : Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) {
    1829             :   // See v8::internal::StubCache::PrimaryOffset().
    1830             :   STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift);
    1831             :   // Compute the hash of the name (use entire hash field).
    1832         346 :   Node* hash_field = LoadNameHashField(name);
    1833             :   CSA_ASSERT(this,
    1834             :              Word32Equal(Word32And(hash_field,
    1835             :                                    Int32Constant(Name::kHashNotComputedMask)),
    1836             :                          Int32Constant(0)));
    1837             : 
    1838             :   // Using only the low bits in 64-bit mode is unlikely to increase the
    1839             :   // risk of collision even if the heap is spread over an area larger than
    1840             :   // 4Gb (and not at all if it isn't).
    1841         519 :   Node* map32 = TruncateWordToWord32(BitcastTaggedToWord(map));
    1842         346 :   Node* hash = Int32Add(hash_field, map32);
    1843             :   // Base the offset on a simple combination of name and map.
    1844         519 :   hash = Word32Xor(hash, Int32Constant(StubCache::kPrimaryMagic));
    1845             :   uint32_t mask = (StubCache::kPrimaryTableSize - 1)
    1846             :                   << StubCache::kCacheIndexShift;
    1847         692 :   return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
    1848             : }
    1849             : 
    1850         167 : Node* AccessorAssembler::StubCacheSecondaryOffset(Node* name, Node* seed) {
    1851             :   // See v8::internal::StubCache::SecondaryOffset().
    1852             : 
    1853             :   // Use the seed from the primary cache in the secondary cache.
    1854         501 :   Node* name32 = TruncateWordToWord32(BitcastTaggedToWord(name));
    1855         501 :   Node* hash = Int32Sub(TruncateWordToWord32(seed), name32);
    1856         501 :   hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic));
    1857             :   int32_t mask = (StubCache::kSecondaryTableSize - 1)
    1858             :                  << StubCache::kCacheIndexShift;
    1859         668 :   return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
    1860             : }
    1861             : 
    1862         322 : void AccessorAssembler::TryProbeStubCacheTable(StubCache* stub_cache,
    1863             :                                                StubCacheTable table_id,
    1864             :                                                Node* entry_offset, Node* name,
    1865             :                                                Node* map, Label* if_handler,
    1866             :                                                Variable* var_handler,
    1867             :                                                Label* if_miss) {
    1868         322 :   StubCache::Table table = static_cast<StubCache::Table>(table_id);
    1869             : #ifdef DEBUG
    1870             :   if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
    1871             :     Goto(if_miss);
    1872             :     return;
    1873             :   } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
    1874             :     Goto(if_miss);
    1875             :     return;
    1876             :   }
    1877             : #endif
    1878             :   // The {table_offset} holds the entry offset times four (due to masking
    1879             :   // and shifting optimizations).
    1880             :   const int kMultiplier = sizeof(StubCache::Entry) >> Name::kHashShift;
    1881         966 :   entry_offset = IntPtrMul(entry_offset, IntPtrConstant(kMultiplier));
    1882             : 
    1883             :   // Check that the key in the entry matches the name.
    1884             :   Node* key_base =
    1885         644 :       ExternalConstant(ExternalReference(stub_cache->key_reference(table)));
    1886         322 :   Node* entry_key = Load(MachineType::Pointer(), key_base, entry_offset);
    1887         644 :   GotoIf(WordNotEqual(name, entry_key), if_miss);
    1888             : 
    1889             :   // Get the map entry from the cache.
    1890             :   DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() -
    1891             :                                   stub_cache->key_reference(table).address());
    1892             :   Node* entry_map =
    1893             :       Load(MachineType::Pointer(), key_base,
    1894         966 :            IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2)));
    1895         644 :   GotoIf(WordNotEqual(map, entry_map), if_miss);
    1896             : 
    1897             :   DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() -
    1898             :                               stub_cache->key_reference(table).address());
    1899             :   Node* handler = Load(MachineType::TaggedPointer(), key_base,
    1900         966 :                        IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize)));
    1901             : 
    1902             :   // We found the handler.
    1903         322 :   var_handler->Bind(handler);
    1904         322 :   Goto(if_handler);
    1905         322 : }
    1906             : 
    1907         161 : void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver,
    1908             :                                           Node* name, Label* if_handler,
    1909             :                                           Variable* var_handler,
    1910             :                                           Label* if_miss) {
    1911         322 :   Label try_secondary(this), miss(this);
    1912             : 
    1913         161 :   Counters* counters = isolate()->counters();
    1914         161 :   IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
    1915             : 
    1916             :   // Check that the {receiver} isn't a smi.
    1917         322 :   GotoIf(TaggedIsSmi(receiver), &miss);
    1918             : 
    1919         322 :   Node* receiver_map = LoadMap(receiver);
    1920             : 
    1921             :   // Probe the primary table.
    1922         161 :   Node* primary_offset = StubCachePrimaryOffset(name, receiver_map);
    1923             :   TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name,
    1924         161 :                          receiver_map, if_handler, var_handler, &try_secondary);
    1925             : 
    1926         161 :   BIND(&try_secondary);
    1927             :   {
    1928             :     // Probe the secondary table.
    1929         161 :     Node* secondary_offset = StubCacheSecondaryOffset(name, primary_offset);
    1930             :     TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
    1931         161 :                            receiver_map, if_handler, var_handler, &miss);
    1932             :   }
    1933             : 
    1934         161 :   BIND(&miss);
    1935             :   {
    1936         161 :     IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
    1937         161 :     Goto(if_miss);
    1938         161 :   }
    1939         161 : }
    1940             : 
    1941             : //////////////////// Entry points into private implementation (one per stub).
    1942             : 
    1943          93 : void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
    1944             :                                                ExitPoint* exit_point) {
    1945             :   // Must be kept in sync with LoadIC.
    1946             : 
    1947             :   // This function is hand-tuned to omit frame construction for common cases,
    1948             :   // e.g.: monomorphic field and constant loads through smi handlers.
    1949             :   // Polymorphic ICs with a hit in the first two entries also omit frames.
    1950             :   // TODO(jgruber): Frame omission is fragile and can be affected by minor
    1951             :   // changes in control flow and logic. We currently have no way of ensuring
    1952             :   // that no frame is constructed, so it's easy to break this optimization by
    1953             :   // accident.
    1954         186 :   Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred);
    1955             : 
    1956             :   // Inlined fast path.
    1957             :   {
    1958          93 :     Comment("LoadIC_BytecodeHandler_fast");
    1959             : 
    1960          93 :     Node* recv_map = LoadReceiverMap(p->receiver);
    1961         186 :     GotoIf(IsDeprecatedMap(recv_map), &miss);
    1962             : 
    1963          93 :     VARIABLE(var_handler, MachineRepresentation::kTagged);
    1964          93 :     Label try_polymorphic(this), if_handler(this, &var_handler);
    1965             : 
    1966             :     Node* feedback =
    1967             :         TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler,
    1968          93 :                            &var_handler, &try_polymorphic);
    1969             : 
    1970          93 :     BIND(&if_handler);
    1971          93 :     HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point);
    1972             : 
    1973          93 :     BIND(&try_polymorphic);
    1974             :     {
    1975         279 :       GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()),
    1976          93 :                 &stub_call);
    1977             :       HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler,
    1978          93 :                             &miss, 2);
    1979          93 :     }
    1980             :   }
    1981             : 
    1982          93 :   BIND(&stub_call);
    1983             :   {
    1984          93 :     Comment("LoadIC_BytecodeHandler_noninlined");
    1985             : 
    1986             :     // Call into the stub that implements the non-inlined parts of LoadIC.
    1987             :     Callable ic =
    1988          93 :         Builtins::CallableFor(isolate(), Builtins::kLoadIC_Noninlined);
    1989             :     Node* code_target = HeapConstant(ic.code());
    1990             :     exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context,
    1991         279 :                                p->receiver, p->name, p->slot, p->vector);
    1992             :   }
    1993             : 
    1994          93 :   BIND(&miss);
    1995             :   {
    1996          93 :     Comment("LoadIC_BytecodeHandler_miss");
    1997             : 
    1998             :     exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context,
    1999          93 :                                   p->receiver, p->name, p->slot, p->vector);
    2000          93 :   }
    2001          93 : }
    2002             : 
    2003          31 : void AccessorAssembler::LoadIC(const LoadICParameters* p) {
    2004             :   // Must be kept in sync with LoadIC_BytecodeHandler.
    2005             : 
    2006          31 :   ExitPoint direct_exit(this);
    2007             : 
    2008          31 :   VARIABLE(var_handler, MachineRepresentation::kTagged);
    2009          31 :   Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred),
    2010          31 :       try_polymorphic(this), miss(this, Label::kDeferred);
    2011             : 
    2012          31 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2013          62 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2014             : 
    2015             :   // Check monomorphic case.
    2016             :   Node* feedback =
    2017             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2018          31 :                          &var_handler, &try_polymorphic);
    2019          31 :   BIND(&if_handler);
    2020          31 :   HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit);
    2021             : 
    2022          31 :   BIND(&try_polymorphic);
    2023             :   {
    2024             :     // Check polymorphic case.
    2025          31 :     Comment("LoadIC_try_polymorphic");
    2026          93 :     GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()),
    2027          31 :               &non_inlined);
    2028             :     HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler,
    2029          31 :                           &miss, 2);
    2030             :   }
    2031             : 
    2032          31 :   BIND(&non_inlined);
    2033             :   LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss,
    2034          31 :                     &direct_exit);
    2035             : 
    2036          31 :   BIND(&miss);
    2037             :   direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver,
    2038          62 :                                 p->name, p->slot, p->vector);
    2039          31 : }
    2040             : 
    2041          62 : void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
    2042             :                                           Node* receiver_map, Node* feedback,
    2043             :                                           Variable* var_handler,
    2044             :                                           Label* if_handler, Label* miss,
    2045             :                                           ExitPoint* exit_point) {
    2046          62 :   Label try_uninitialized(this, Label::kDeferred);
    2047             : 
    2048             :   // Neither deprecated map nor monomorphic. These cases are handled in the
    2049             :   // bytecode handler.
    2050             :   CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
    2051             :   CSA_ASSERT(this,
    2052             :              WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)));
    2053             :   CSA_ASSERT(this, WordNotEqual(LoadMap(feedback), FixedArrayMapConstant()));
    2054             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
    2055             : 
    2056             :   {
    2057             :     // Check megamorphic case.
    2058          62 :     GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
    2059          62 :               &try_uninitialized);
    2060             : 
    2061             :     TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
    2062          62 :                       if_handler, var_handler, miss);
    2063             :   }
    2064             : 
    2065          62 :   BIND(&try_uninitialized);
    2066             :   {
    2067             :     // Check uninitialized case.
    2068             :     GotoIfNot(
    2069          62 :         WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
    2070          62 :         miss);
    2071             :     exit_point->ReturnCallStub(
    2072             :         Builtins::CallableFor(isolate(), Builtins::kLoadIC_Uninitialized),
    2073         124 :         p->context, p->receiver, p->name, p->slot, p->vector);
    2074          62 :   }
    2075          62 : }
    2076             : 
    2077          31 : void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
    2078          31 :   Label miss(this, Label::kDeferred);
    2079          31 :   Node* receiver = p->receiver;
    2080          62 :   GotoIf(TaggedIsSmi(receiver), &miss);
    2081          62 :   Node* receiver_map = LoadMap(receiver);
    2082          62 :   Node* instance_type = LoadMapInstanceType(receiver_map);
    2083             : 
    2084             :   // Optimistically write the state transition to the vector.
    2085             :   StoreFeedbackVectorSlot(p->vector, p->slot,
    2086             :                           LoadRoot(Heap::kpremonomorphic_symbolRootIndex),
    2087          62 :                           SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
    2088             : 
    2089             :   {
    2090             :     // Special case for Function.prototype load, because it's very common
    2091             :     // for ICs that are only executed once (MyFunc.prototype.foo = ...).
    2092             :     Label not_function_prototype(this, Label::kDeferred);
    2093             :     GotoIfNot(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE),
    2094          62 :               &not_function_prototype);
    2095          93 :     GotoIfNot(IsPrototypeString(p->name), &not_function_prototype);
    2096             : 
    2097             :     // if (!(has_prototype_slot() && !has_non_instance_prototype())) use generic
    2098             :     // property loading mechanism.
    2099             :     int has_prototype_slot_mask = 1 << Map::kHasPrototypeSlot;
    2100             :     int has_non_instance_prototype_mask = 1 << Map::kHasNonInstancePrototype;
    2101             :     GotoIfNot(
    2102          31 :         Word32Equal(Word32And(LoadMapBitField(receiver_map),
    2103             :                               Int32Constant(has_prototype_slot_mask |
    2104         124 :                                             has_non_instance_prototype_mask)),
    2105         124 :                     Int32Constant(has_prototype_slot_mask)),
    2106          62 :         &not_function_prototype);
    2107          62 :     Return(LoadJSFunctionPrototype(receiver, &miss));
    2108          31 :     BIND(&not_function_prototype);
    2109             :   }
    2110             : 
    2111             :   GenericPropertyLoad(receiver, receiver_map, instance_type, p, &miss,
    2112          31 :                       kDontUseStubCache);
    2113             : 
    2114          31 :   BIND(&miss);
    2115             :   {
    2116             :     // Undo the optimistic state transition.
    2117             :     StoreFeedbackVectorSlot(p->vector, p->slot,
    2118             :                             LoadRoot(Heap::kuninitialized_symbolRootIndex),
    2119          62 :                             SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
    2120             : 
    2121             :     TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
    2122          31 :                     p->slot, p->vector);
    2123          31 :   }
    2124          31 : }
    2125             : 
    2126          62 : void AccessorAssembler::LoadICProtoArray(
    2127             :     const LoadICParameters* p, Node* handler,
    2128             :     bool throw_reference_error_if_nonexistent) {
    2129          62 :   Label miss(this);
    2130             :   CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler)));
    2131             :   CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler)));
    2132             : 
    2133          62 :   ExitPoint direct_exit(this);
    2134             : 
    2135             :   Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset);
    2136         124 :   Node* handler_flags = SmiUntag(smi_handler);
    2137             : 
    2138         124 :   Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler);
    2139             : 
    2140             :   Node* holder = EmitLoadICProtoArrayCheck(p, handler, handler_length,
    2141          62 :                                            handler_flags, &miss);
    2142             : 
    2143             :   HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, &direct_exit,
    2144             :                              throw_reference_error_if_nonexistent,
    2145          62 :                              kOnlyProperties);
    2146             : 
    2147          62 :   BIND(&miss);
    2148             :   {
    2149             :     TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
    2150          62 :                     p->slot, p->vector);
    2151          62 :   }
    2152          62 : }
    2153             : 
    2154         434 : void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
    2155             :     Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler,
    2156             :     Label* miss, ParameterMode slot_mode) {
    2157         434 :   Comment("LoadGlobalIC_TryPropertyCellCase");
    2158             : 
    2159         434 :   Node* weak_cell = LoadFeedbackVectorSlot(vector, slot, 0, slot_mode);
    2160             :   CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE));
    2161             : 
    2162             :   // Load value or try handler case if the {weak_cell} is cleared.
    2163         434 :   Node* property_cell = LoadWeakCellValue(weak_cell, try_handler);
    2164             :   CSA_ASSERT(this, IsPropertyCell(property_cell));
    2165             : 
    2166             :   Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
    2167         868 :   GotoIf(WordEqual(value, TheHoleConstant()), miss);
    2168         434 :   exit_point->Return(value);
    2169         434 : }
    2170             : 
    2171         434 : void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* pp,
    2172             :                                                     TypeofMode typeof_mode,
    2173             :                                                     ExitPoint* exit_point,
    2174             :                                                     Label* miss) {
    2175         434 :   Comment("LoadGlobalIC_TryHandlerCase");
    2176             : 
    2177         434 :   Label call_handler(this), non_smi(this);
    2178             : 
    2179             :   Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize,
    2180         434 :                                          SMI_PARAMETERS);
    2181         434 :   GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
    2182         434 :          miss);
    2183             : 
    2184         868 :   GotoIfNot(TaggedIsSmi(handler), &non_smi);
    2185             : 
    2186         434 :   bool throw_reference_error_if_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF;
    2187             : 
    2188             :   {
    2189         434 :     LoadICParameters p = *pp;
    2190             :     DCHECK_NULL(p.receiver);
    2191        1302 :     Node* native_context = LoadNativeContext(p.context);
    2192         868 :     p.receiver =
    2193         868 :         LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
    2194         868 :     Node* holder = LoadContextElement(native_context, Context::EXTENSION_INDEX);
    2195             :     HandleLoadICSmiHandlerCase(&p, holder, handler, miss, exit_point,
    2196             :                                throw_reference_error_if_nonexistent,
    2197         434 :                                kOnlyProperties);
    2198             :   }
    2199             : 
    2200         434 :   BIND(&non_smi);
    2201        1302 :   GotoIf(IsCodeMap(LoadMap(handler)), &call_handler);
    2202             : 
    2203             :   HandleLoadGlobalICHandlerCase(pp, handler, miss, exit_point,
    2204         434 :                                 throw_reference_error_if_nonexistent);
    2205             : 
    2206         434 :   BIND(&call_handler);
    2207             :   {
    2208         434 :     LoadWithVectorDescriptor descriptor(isolate());
    2209        1302 :     Node* native_context = LoadNativeContext(pp->context);
    2210             :     Node* receiver =
    2211         868 :         LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
    2212             :     exit_point->ReturnCallStub(descriptor, handler, pp->context, receiver,
    2213         434 :                                pp->name, pp->slot, pp->vector);
    2214         434 :   }
    2215         434 : }
    2216             : 
    2217         434 : void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p,
    2218             :                                               ExitPoint* exit_point) {
    2219         434 :   Comment("LoadGlobalIC_MissCase");
    2220             : 
    2221             :   exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context,
    2222         434 :                                 p->name, p->slot, p->vector);
    2223         434 : }
    2224             : 
    2225          62 : void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p,
    2226             :                                      TypeofMode typeof_mode) {
    2227             :   // Must be kept in sync with Interpreter::BuildLoadGlobal.
    2228             : 
    2229          62 :   ExitPoint direct_exit(this);
    2230             : 
    2231         124 :   Label try_handler(this), miss(this);
    2232             :   LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit,
    2233          62 :                                    &try_handler, &miss);
    2234             : 
    2235          62 :   BIND(&try_handler);
    2236          62 :   LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss);
    2237             : 
    2238          62 :   BIND(&miss);
    2239         124 :   LoadGlobalIC_MissCase(p, &direct_exit);
    2240          62 : }
    2241             : 
    2242          31 : void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
    2243          31 :   ExitPoint direct_exit(this);
    2244             : 
    2245          31 :   VARIABLE(var_handler, MachineRepresentation::kTagged);
    2246          31 :   Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
    2247          31 :       try_megamorphic(this, Label::kDeferred),
    2248          31 :       try_polymorphic_name(this, Label::kDeferred),
    2249          31 :       miss(this, Label::kDeferred);
    2250             : 
    2251          31 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2252          62 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2253             : 
    2254             :   // Check monomorphic case.
    2255             :   Node* feedback =
    2256             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2257          31 :                          &var_handler, &try_polymorphic);
    2258          31 :   BIND(&if_handler);
    2259             :   {
    2260             :     HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit,
    2261          31 :                             kSupportElements);
    2262             :   }
    2263             : 
    2264          31 :   BIND(&try_polymorphic);
    2265             :   {
    2266             :     // Check polymorphic case.
    2267          31 :     Comment("KeyedLoadIC_try_polymorphic");
    2268          93 :     GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()),
    2269          31 :               &try_megamorphic);
    2270             :     HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler,
    2271          31 :                           &miss, 2);
    2272             :   }
    2273             : 
    2274          31 :   BIND(&try_megamorphic);
    2275             :   {
    2276             :     // Check megamorphic case.
    2277          31 :     Comment("KeyedLoadIC_try_megamorphic");
    2278          31 :     GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
    2279          31 :               &try_polymorphic_name);
    2280             :     // TODO(jkummerow): Inline this? Or some of it?
    2281             :     TailCallStub(
    2282             :         Builtins::CallableFor(isolate(), Builtins::kKeyedLoadIC_Megamorphic),
    2283          62 :         p->context, p->receiver, p->name, p->slot, p->vector);
    2284             :   }
    2285          31 :   BIND(&try_polymorphic_name);
    2286             :   {
    2287             :     // We might have a name in feedback, and a fixed array in the next slot.
    2288          31 :     Node* name = p->name;
    2289          31 :     Comment("KeyedLoadIC_try_polymorphic_name");
    2290          31 :     VARIABLE(var_name, MachineRepresentation::kTagged, name);
    2291          62 :     VARIABLE(var_index, MachineType::PointerRepresentation());
    2292          31 :     Label if_polymorphic_name(this, &var_name), if_internalized(this),
    2293          31 :         if_notinternalized(this, Label::kDeferred);
    2294             : 
    2295             :     // Fast-case: The recorded {feedback} matches the {name}.
    2296          62 :     GotoIf(WordEqual(feedback, name), &if_polymorphic_name);
    2297             : 
    2298             :     // Try to internalize the {name} if it isn't already.
    2299             :     TryToName(name, &miss, &var_index, &if_internalized, &var_name, &miss,
    2300          31 :               &if_notinternalized);
    2301             : 
    2302          31 :     BIND(&if_internalized);
    2303             :     {
    2304             :       // The {var_name} now contains a unique name.
    2305          62 :       Branch(WordEqual(feedback, var_name.value()), &if_polymorphic_name,
    2306          62 :              &miss);
    2307             :     }
    2308             : 
    2309          31 :     BIND(&if_notinternalized);
    2310             :     {
    2311             :       // Try to internalize the {name}.
    2312             :       Node* function = ExternalConstant(
    2313          62 :           ExternalReference::try_internalize_string_function(isolate()));
    2314             :       var_name.Bind(CallCFunction1(MachineType::AnyTagged(),
    2315          31 :                                    MachineType::AnyTagged(), function, name));
    2316          31 :       Goto(&if_internalized);
    2317             :     }
    2318             : 
    2319          31 :     BIND(&if_polymorphic_name);
    2320             :     {
    2321             :       // If the name comparison succeeded, we know we have a fixed array with
    2322             :       // at least one map/handler pair.
    2323          31 :       Node* name = var_name.value();
    2324             :       TailCallBuiltin(Builtins::kKeyedLoadIC_PolymorphicName, p->context,
    2325          31 :                       p->receiver, name, p->slot, p->vector);
    2326          31 :     }
    2327             :   }
    2328             : 
    2329          31 :   BIND(&miss);
    2330             :   {
    2331          31 :     Comment("KeyedLoadIC_miss");
    2332             :     TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
    2333          31 :                     p->name, p->slot, p->vector);
    2334          31 :   }
    2335          31 : }
    2336             : 
    2337          31 : void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
    2338          31 :   VARIABLE(var_index, MachineType::PointerRepresentation());
    2339          62 :   VARIABLE(var_unique, MachineRepresentation::kTagged);
    2340          31 :   var_unique.Bind(p->name);  // Dummy initialization.
    2341          31 :   Label if_index(this), if_unique_name(this), if_notunique(this), slow(this);
    2342             : 
    2343          31 :   Node* receiver = p->receiver;
    2344          62 :   GotoIf(TaggedIsSmi(receiver), &slow);
    2345          62 :   Node* receiver_map = LoadMap(receiver);
    2346          62 :   Node* instance_type = LoadMapInstanceType(receiver_map);
    2347             : 
    2348             :   TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique, &slow,
    2349          31 :             &if_notunique);
    2350             : 
    2351          31 :   BIND(&if_index);
    2352             :   {
    2353             :     GenericElementLoad(receiver, receiver_map, instance_type, var_index.value(),
    2354          31 :                        &slow);
    2355             :   }
    2356             : 
    2357          31 :   BIND(&if_unique_name);
    2358             :   {
    2359          31 :     LoadICParameters pp = *p;
    2360          31 :     pp.name = var_unique.value();
    2361          31 :     GenericPropertyLoad(receiver, receiver_map, instance_type, &pp, &slow);
    2362             :   }
    2363             : 
    2364          31 :   BIND(&if_notunique);
    2365             :   {
    2366             :     if (FLAG_internalize_on_the_fly) {
    2367             :       Label not_in_string_table(this);
    2368             :       TryInternalizeString(p->name, &if_index, &var_index, &if_unique_name,
    2369             :                            &var_unique, &not_in_string_table, &slow);
    2370             : 
    2371             :       BIND(&not_in_string_table);
    2372             :       // If the string was not found in the string table, then no object can
    2373             :       // have a property with that name.
    2374             :       Return(UndefinedConstant());
    2375             :     } else {
    2376          31 :       Goto(&slow);
    2377             :     }
    2378             :   }
    2379             : 
    2380          31 :   BIND(&slow);
    2381             :   {
    2382          31 :     Comment("KeyedLoadGeneric_slow");
    2383          62 :     IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
    2384             :     // TODO(jkummerow): Should we use the GetProperty TF stub instead?
    2385             :     TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver,
    2386          31 :                     p->name);
    2387          31 :   }
    2388          31 : }
    2389             : 
    2390          31 : void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) {
    2391          31 :   VARIABLE(var_handler, MachineRepresentation::kTagged);
    2392          31 :   Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
    2393             : 
    2394          31 :   Node* receiver = p->receiver;
    2395          31 :   Node* receiver_map = LoadReceiverMap(receiver);
    2396          31 :   Node* name = p->name;
    2397          31 :   Node* vector = p->vector;
    2398          31 :   Node* slot = p->slot;
    2399          31 :   Node* context = p->context;
    2400             : 
    2401             :   // When we get here, we know that the {name} matches the recorded
    2402             :   // feedback name in the {vector} and can safely be used for the
    2403             :   // LoadIC handler logic below.
    2404             :   CSA_ASSERT(this, IsName(name));
    2405             :   CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
    2406             :   CSA_ASSERT(this, WordEqual(name, LoadFeedbackVectorSlot(vector, slot, 0,
    2407             :                                                           SMI_PARAMETERS)));
    2408             : 
    2409             :   // Check if we have a matching handler for the {receiver_map}.
    2410             :   Node* array =
    2411          31 :       LoadFeedbackVectorSlot(vector, slot, kPointerSize, SMI_PARAMETERS);
    2412             :   HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss,
    2413          31 :                         1);
    2414             : 
    2415          31 :   BIND(&if_handler);
    2416             :   {
    2417             :     ExitPoint direct_exit(this);
    2418             :     HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit,
    2419          31 :                             kOnlyProperties);
    2420             :   }
    2421             : 
    2422          31 :   BIND(&miss);
    2423             :   {
    2424          31 :     Comment("KeyedLoadIC_miss");
    2425             :     TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot,
    2426             :                     vector);
    2427          31 :   }
    2428          31 : }
    2429             : 
    2430          31 : void AccessorAssembler::StoreIC(const StoreICParameters* p) {
    2431          31 :   VARIABLE(var_handler, MachineRepresentation::kTagged);
    2432          31 :   Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
    2433          31 :       try_megamorphic(this, Label::kDeferred),
    2434          31 :       try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred);
    2435             : 
    2436          31 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2437          62 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2438             : 
    2439             :   // Check monomorphic case.
    2440             :   Node* feedback =
    2441             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2442          31 :                          &var_handler, &try_polymorphic);
    2443          31 :   BIND(&if_handler);
    2444             :   {
    2445          31 :     Comment("StoreIC_if_handler");
    2446          31 :     HandleStoreICHandlerCase(p, var_handler.value(), &miss);
    2447             :   }
    2448             : 
    2449          31 :   BIND(&try_polymorphic);
    2450             :   {
    2451             :     // Check polymorphic case.
    2452          31 :     Comment("StoreIC_try_polymorphic");
    2453             :     GotoIfNot(
    2454          93 :         WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
    2455          31 :         &try_megamorphic);
    2456             :     HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler,
    2457          31 :                           &miss, 2);
    2458             :   }
    2459             : 
    2460          31 :   BIND(&try_megamorphic);
    2461             :   {
    2462             :     // Check megamorphic case.
    2463          31 :     GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
    2464          31 :               &try_uninitialized);
    2465             : 
    2466             :     TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
    2467          31 :                       &if_handler, &var_handler, &miss);
    2468             :   }
    2469          31 :   BIND(&try_uninitialized);
    2470             :   {
    2471             :     // Check uninitialized case.
    2472             :     GotoIfNot(
    2473          31 :         WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
    2474          31 :         &miss);
    2475             :     Callable stub =
    2476          31 :         Builtins::CallableFor(isolate(), Builtins::kStoreIC_Uninitialized);
    2477             :     TailCallStub(stub, p->context, p->receiver, p->name, p->value, p->slot,
    2478          31 :                  p->vector);
    2479             :   }
    2480          31 :   BIND(&miss);
    2481             :   {
    2482             :     TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot,
    2483          31 :                     p->vector, p->receiver, p->name);
    2484          31 :   }
    2485          31 : }
    2486             : 
    2487         310 : void AccessorAssembler::StoreGlobalIC_PropertyCellCase(Node* property_cell,
    2488             :                                                        Node* value,
    2489             :                                                        ExitPoint* exit_point,
    2490             :                                                        Label* miss) {
    2491         310 :   Comment("StoreGlobalIC_TryPropertyCellCase");
    2492             :   CSA_ASSERT(this, IsPropertyCell(property_cell));
    2493             : 
    2494             :   // Load the payload of the global parameter cell. A hole indicates that
    2495             :   // the cell has been invalidated and that the store must be handled by the
    2496             :   // runtime.
    2497             :   Node* cell_contents =
    2498         310 :       LoadObjectField(property_cell, PropertyCell::kValueOffset);
    2499             :   Node* details = LoadAndUntagToWord32ObjectField(property_cell,
    2500         620 :                                                   PropertyCell::kDetailsOffset);
    2501             :   Node* type = DecodeWord32<PropertyDetails::PropertyCellTypeField>(details);
    2502             : 
    2503         310 :   Label constant(this), store(this), not_smi(this);
    2504             : 
    2505             :   GotoIf(Word32Equal(type, Int32Constant(
    2506         620 :                                static_cast<int>(PropertyCellType::kConstant))),
    2507         620 :          &constant);
    2508             : 
    2509         620 :   GotoIf(IsTheHole(cell_contents), miss);
    2510             : 
    2511             :   GotoIf(Word32Equal(
    2512         620 :              type, Int32Constant(static_cast<int>(PropertyCellType::kMutable))),
    2513         620 :          &store);
    2514             :   CSA_ASSERT(this,
    2515             :              Word32Or(Word32Equal(type, Int32Constant(static_cast<int>(
    2516             :                                             PropertyCellType::kConstantType))),
    2517             :                       Word32Equal(type, Int32Constant(static_cast<int>(
    2518             :                                             PropertyCellType::kUndefined)))));
    2519             : 
    2520         620 :   GotoIfNot(TaggedIsSmi(cell_contents), &not_smi);
    2521         620 :   GotoIfNot(TaggedIsSmi(value), miss);
    2522         310 :   Goto(&store);
    2523             : 
    2524         310 :   BIND(&not_smi);
    2525             :   {
    2526         620 :     GotoIf(TaggedIsSmi(value), miss);
    2527         620 :     Node* expected_map = LoadMap(cell_contents);
    2528         620 :     Node* map = LoadMap(value);
    2529         620 :     GotoIfNot(WordEqual(expected_map, map), miss);
    2530         310 :     Goto(&store);
    2531             :   }
    2532             : 
    2533         310 :   BIND(&store);
    2534             :   {
    2535         310 :     StoreObjectField(property_cell, PropertyCell::kValueOffset, value);
    2536         310 :     exit_point->Return(value);
    2537             :   }
    2538             : 
    2539         310 :   BIND(&constant);
    2540             :   {
    2541         620 :     GotoIfNot(WordEqual(cell_contents, value), miss);
    2542         310 :     exit_point->Return(value);
    2543         310 :   }
    2544         310 : }
    2545             : 
    2546          31 : void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
    2547          31 :   Label miss(this, Label::kDeferred);
    2548             :   {
    2549          31 :     VARIABLE(var_handler, MachineRepresentation::kTagged);
    2550             : 
    2551          31 :     Label if_handler(this, &var_handler),
    2552          31 :         try_polymorphic(this, Label::kDeferred),
    2553          31 :         try_megamorphic(this, Label::kDeferred),
    2554          31 :         try_polymorphic_name(this, Label::kDeferred);
    2555             : 
    2556          31 :     Node* receiver_map = LoadReceiverMap(p->receiver);
    2557          62 :     GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2558             : 
    2559             :     // Check monomorphic case.
    2560             :     Node* feedback =
    2561             :         TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2562          31 :                            &var_handler, &try_polymorphic);
    2563          31 :     BIND(&if_handler);
    2564             :     {
    2565          31 :       Comment("KeyedStoreIC_if_handler");
    2566          31 :       HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements);
    2567             :     }
    2568             : 
    2569          31 :     BIND(&try_polymorphic);
    2570             :     {
    2571             :       // CheckPolymorphic case.
    2572          31 :       Comment("KeyedStoreIC_try_polymorphic");
    2573             :       GotoIfNot(
    2574          93 :           WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
    2575          31 :           &try_megamorphic);
    2576             :       HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler,
    2577          31 :                             &miss, 2);
    2578             :     }
    2579             : 
    2580          31 :     BIND(&try_megamorphic);
    2581             :     {
    2582             :       // Check megamorphic case.
    2583          31 :       Comment("KeyedStoreIC_try_megamorphic");
    2584             :       GotoIfNot(
    2585          31 :           WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)),
    2586          31 :           &try_polymorphic_name);
    2587             :       TailCallStub(
    2588             :           Builtins::CallableFor(isolate(), Builtins::kKeyedStoreIC_Megamorphic),
    2589          62 :           p->context, p->receiver, p->name, p->value, p->slot, p->vector);
    2590             :     }
    2591             : 
    2592          31 :     BIND(&try_polymorphic_name);
    2593             :     {
    2594             :       // We might have a name in feedback, and a fixed array in the next slot.
    2595          31 :       Comment("KeyedStoreIC_try_polymorphic_name");
    2596          93 :       GotoIfNot(WordEqual(feedback, p->name), &miss);
    2597             :       // If the name comparison succeeded, we know we have a feedback vector
    2598             :       // with at least one map/handler pair.
    2599             :       Node* array = LoadFeedbackVectorSlot(p->vector, p->slot, kPointerSize,
    2600          31 :                                            SMI_PARAMETERS);
    2601             :       HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
    2602          31 :                             &miss, 1);
    2603          31 :     }
    2604             :   }
    2605          31 :   BIND(&miss);
    2606             :   {
    2607          31 :     Comment("KeyedStoreIC_miss");
    2608             :     TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
    2609          31 :                     p->vector, p->receiver, p->name);
    2610          31 :   }
    2611          31 : }
    2612             : 
    2613             : //////////////////// Public methods.
    2614             : 
    2615          31 : void AccessorAssembler::GenerateLoadIC() {
    2616             :   typedef LoadWithVectorDescriptor Descriptor;
    2617             : 
    2618          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2619          31 :   Node* name = Parameter(Descriptor::kName);
    2620          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2621          31 :   Node* vector = Parameter(Descriptor::kVector);
    2622          31 :   Node* context = Parameter(Descriptor::kContext);
    2623             : 
    2624             :   LoadICParameters p(context, receiver, name, slot, vector);
    2625          31 :   LoadIC(&p);
    2626          31 : }
    2627             : 
    2628          31 : void AccessorAssembler::GenerateLoadIC_Noninlined() {
    2629             :   typedef LoadWithVectorDescriptor Descriptor;
    2630             : 
    2631          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2632          31 :   Node* name = Parameter(Descriptor::kName);
    2633          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2634          31 :   Node* vector = Parameter(Descriptor::kVector);
    2635          31 :   Node* context = Parameter(Descriptor::kContext);
    2636             : 
    2637          31 :   ExitPoint direct_exit(this);
    2638          31 :   VARIABLE(var_handler, MachineRepresentation::kTagged);
    2639          31 :   Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
    2640             : 
    2641          31 :   Node* receiver_map = LoadReceiverMap(receiver);
    2642          31 :   Node* feedback = LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS);
    2643             : 
    2644             :   LoadICParameters p(context, receiver, name, slot, vector);
    2645             :   LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler,
    2646          31 :                     &miss, &direct_exit);
    2647             : 
    2648          31 :   BIND(&if_handler);
    2649          31 :   HandleLoadICHandlerCase(&p, var_handler.value(), &miss, &direct_exit);
    2650             : 
    2651          31 :   BIND(&miss);
    2652             :   direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
    2653          62 :                                 slot, vector);
    2654          31 : }
    2655             : 
    2656          31 : void AccessorAssembler::GenerateLoadIC_Uninitialized() {
    2657             :   typedef LoadWithVectorDescriptor Descriptor;
    2658             : 
    2659          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2660          31 :   Node* name = Parameter(Descriptor::kName);
    2661          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2662          31 :   Node* vector = Parameter(Descriptor::kVector);
    2663          31 :   Node* context = Parameter(Descriptor::kContext);
    2664             : 
    2665             :   LoadICParameters p(context, receiver, name, slot, vector);
    2666          31 :   LoadIC_Uninitialized(&p);
    2667          31 : }
    2668             : 
    2669          31 : void AccessorAssembler::GenerateLoadICTrampoline() {
    2670             :   typedef LoadDescriptor Descriptor;
    2671             : 
    2672          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2673          31 :   Node* name = Parameter(Descriptor::kName);
    2674          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2675          31 :   Node* context = Parameter(Descriptor::kContext);
    2676          31 :   Node* vector = LoadFeedbackVectorForStub();
    2677             : 
    2678          31 :   TailCallBuiltin(Builtins::kLoadIC, context, receiver, name, slot, vector);
    2679          31 : }
    2680             : 
    2681          62 : void AccessorAssembler::GenerateLoadICProtoArray(
    2682             :     bool throw_reference_error_if_nonexistent) {
    2683             :   typedef LoadICProtoArrayDescriptor Descriptor;
    2684             : 
    2685          62 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2686          62 :   Node* name = Parameter(Descriptor::kName);
    2687          62 :   Node* slot = Parameter(Descriptor::kSlot);
    2688          62 :   Node* vector = Parameter(Descriptor::kVector);
    2689          62 :   Node* handler = Parameter(Descriptor::kHandler);
    2690          62 :   Node* context = Parameter(Descriptor::kContext);
    2691             : 
    2692             :   LoadICParameters p(context, receiver, name, slot, vector);
    2693          62 :   LoadICProtoArray(&p, handler, throw_reference_error_if_nonexistent);
    2694          62 : }
    2695             : 
    2696          31 : void AccessorAssembler::GenerateLoadField() {
    2697             :   typedef LoadFieldDescriptor Descriptor;
    2698             : 
    2699          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2700             :   Node* name = nullptr;
    2701             :   Node* slot = nullptr;
    2702             :   Node* vector = nullptr;
    2703          31 :   Node* context = Parameter(Descriptor::kContext);
    2704             :   LoadICParameters p(context, receiver, name, slot, vector);
    2705             : 
    2706          31 :   ExitPoint direct_exit(this);
    2707             : 
    2708          31 :   VARIABLE(var_double_value, MachineRepresentation::kFloat64);
    2709          31 :   Label rebox_double(this, &var_double_value);
    2710             : 
    2711          31 :   Node* smi_handler = Parameter(Descriptor::kSmiHandler);
    2712          62 :   Node* handler_word = SmiUntag(smi_handler);
    2713             :   HandleLoadField(receiver, handler_word, &var_double_value, &rebox_double,
    2714          31 :                   &direct_exit);
    2715             : 
    2716          31 :   BIND(&rebox_double);
    2717         124 :   Return(AllocateHeapNumberWithValue(var_double_value.value()));
    2718          31 : }
    2719             : 
    2720          62 : void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
    2721             :   typedef LoadGlobalWithVectorDescriptor Descriptor;
    2722             : 
    2723          62 :   Node* name = Parameter(Descriptor::kName);
    2724          62 :   Node* slot = Parameter(Descriptor::kSlot);
    2725          62 :   Node* vector = Parameter(Descriptor::kVector);
    2726          62 :   Node* context = Parameter(Descriptor::kContext);
    2727             : 
    2728             :   LoadICParameters p(context, nullptr, name, slot, vector);
    2729          62 :   LoadGlobalIC(&p, typeof_mode);
    2730          62 : }
    2731             : 
    2732          62 : void AccessorAssembler::GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode) {
    2733             :   typedef LoadGlobalDescriptor Descriptor;
    2734             : 
    2735          62 :   Node* name = Parameter(Descriptor::kName);
    2736          62 :   Node* slot = Parameter(Descriptor::kSlot);
    2737          62 :   Node* context = Parameter(Descriptor::kContext);
    2738          62 :   Node* vector = LoadFeedbackVectorForStub();
    2739             : 
    2740             :   Callable callable =
    2741          62 :       CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode);
    2742          62 :   TailCallStub(callable, context, name, slot, vector);
    2743          62 : }
    2744             : 
    2745          31 : void AccessorAssembler::GenerateKeyedLoadIC() {
    2746             :   typedef LoadWithVectorDescriptor Descriptor;
    2747             : 
    2748          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2749          31 :   Node* name = Parameter(Descriptor::kName);
    2750          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2751          31 :   Node* vector = Parameter(Descriptor::kVector);
    2752          31 :   Node* context = Parameter(Descriptor::kContext);
    2753             : 
    2754             :   LoadICParameters p(context, receiver, name, slot, vector);
    2755          31 :   KeyedLoadIC(&p);
    2756          31 : }
    2757             : 
    2758          31 : void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
    2759             :   typedef LoadDescriptor Descriptor;
    2760             : 
    2761          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2762          31 :   Node* name = Parameter(Descriptor::kName);
    2763          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2764          31 :   Node* context = Parameter(Descriptor::kContext);
    2765          31 :   Node* vector = LoadFeedbackVectorForStub();
    2766             : 
    2767             :   TailCallBuiltin(Builtins::kKeyedLoadIC, context, receiver, name, slot,
    2768          31 :                   vector);
    2769          31 : }
    2770             : 
    2771          31 : void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
    2772             :   typedef LoadWithVectorDescriptor Descriptor;
    2773             : 
    2774          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2775          31 :   Node* name = Parameter(Descriptor::kName);
    2776          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2777          31 :   Node* vector = Parameter(Descriptor::kVector);
    2778          31 :   Node* context = Parameter(Descriptor::kContext);
    2779             : 
    2780             :   LoadICParameters p(context, receiver, name, slot, vector);
    2781          31 :   KeyedLoadICGeneric(&p);
    2782          31 : }
    2783             : 
    2784          31 : void AccessorAssembler::GenerateKeyedLoadIC_PolymorphicName() {
    2785             :   typedef LoadWithVectorDescriptor Descriptor;
    2786             : 
    2787          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2788          31 :   Node* name = Parameter(Descriptor::kName);
    2789          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2790          31 :   Node* vector = Parameter(Descriptor::kVector);
    2791          31 :   Node* context = Parameter(Descriptor::kContext);
    2792             : 
    2793             :   LoadICParameters p(context, receiver, name, slot, vector);
    2794          31 :   KeyedLoadICPolymorphicName(&p);
    2795          31 : }
    2796             : 
    2797          31 : void AccessorAssembler::GenerateStoreIC() {
    2798             :   typedef StoreWithVectorDescriptor Descriptor;
    2799             : 
    2800          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2801          31 :   Node* name = Parameter(Descriptor::kName);
    2802          31 :   Node* value = Parameter(Descriptor::kValue);
    2803          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2804          31 :   Node* vector = Parameter(Descriptor::kVector);
    2805          31 :   Node* context = Parameter(Descriptor::kContext);
    2806             : 
    2807             :   StoreICParameters p(context, receiver, name, value, slot, vector);
    2808          31 :   StoreIC(&p);
    2809          31 : }
    2810             : 
    2811          31 : void AccessorAssembler::GenerateStoreICTrampoline() {
    2812             :   typedef StoreDescriptor Descriptor;
    2813             : 
    2814          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2815          31 :   Node* name = Parameter(Descriptor::kName);
    2816          31 :   Node* value = Parameter(Descriptor::kValue);
    2817          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2818          31 :   Node* context = Parameter(Descriptor::kContext);
    2819          31 :   Node* vector = LoadFeedbackVectorForStub();
    2820             : 
    2821          31 :   Callable callable = Builtins::CallableFor(isolate(), Builtins::kStoreIC);
    2822          31 :   TailCallStub(callable, context, receiver, name, value, slot, vector);
    2823          31 : }
    2824             : 
    2825          31 : void AccessorAssembler::GenerateKeyedStoreIC() {
    2826             :   typedef StoreWithVectorDescriptor Descriptor;
    2827             : 
    2828          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2829          31 :   Node* name = Parameter(Descriptor::kName);
    2830          31 :   Node* value = Parameter(Descriptor::kValue);
    2831          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2832          31 :   Node* vector = Parameter(Descriptor::kVector);
    2833          31 :   Node* context = Parameter(Descriptor::kContext);
    2834             : 
    2835             :   StoreICParameters p(context, receiver, name, value, slot, vector);
    2836          31 :   KeyedStoreIC(&p);
    2837          31 : }
    2838             : 
    2839          31 : void AccessorAssembler::GenerateKeyedStoreICTrampoline() {
    2840             :   typedef StoreDescriptor Descriptor;
    2841             : 
    2842          31 :   Node* receiver = Parameter(Descriptor::kReceiver);
    2843          31 :   Node* name = Parameter(Descriptor::kName);
    2844          31 :   Node* value = Parameter(Descriptor::kValue);
    2845          31 :   Node* slot = Parameter(Descriptor::kSlot);
    2846          31 :   Node* context = Parameter(Descriptor::kContext);
    2847          31 :   Node* vector = LoadFeedbackVectorForStub();
    2848             : 
    2849          31 :   Callable callable = Builtins::CallableFor(isolate(), Builtins::kKeyedStoreIC);
    2850          31 :   TailCallStub(callable, context, receiver, name, value, slot, vector);
    2851          31 : }
    2852             : 
    2853             : }  // namespace internal
    2854             : }  // namespace v8

Generated by: LCOV version 1.10