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

Generated by: LCOV version 1.10