LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1662 1672 99.4 %
Date: 2019-01-20 Functions: 84 86 97.7 %

          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/ast/ast.h"
       8             : #include "src/code-factory.h"
       9             : #include "src/counters.h"
      10             : #include "src/ic/handler-configuration.h"
      11             : #include "src/ic/ic.h"
      12             : #include "src/ic/keyed-store-generic.h"
      13             : #include "src/ic/stub-cache.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/cell.h"
      16             : #include "src/objects/foreign.h"
      17             : #include "src/objects/heap-number.h"
      18             : #include "src/objects/module.h"
      19             : #include "src/objects/smi.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : 
      24             : using compiler::CodeAssemblerState;
      25             : using compiler::Node;
      26             : template <typename T>
      27             : using TNode = compiler::TNode<T>;
      28             : template <typename T>
      29             : using SloppyTNode = compiler::SloppyTNode<T>;
      30             : 
      31             : //////////////////// Private helpers.
      32             : 
      33             : // Loads dataX field from the DataHandler object.
      34        5096 : TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField(
      35             :     SloppyTNode<DataHandler> handler, int data_index) {
      36             : #ifdef DEBUG
      37             :   TNode<Map> handler_map = LoadMap(handler);
      38             :   TNode<Int32T> instance_type = LoadMapInstanceType(handler_map);
      39             : #endif
      40             :   CSA_ASSERT(this,
      41             :              Word32Or(InstanceTypeEqual(instance_type, LOAD_HANDLER_TYPE),
      42             :                       InstanceTypeEqual(instance_type, STORE_HANDLER_TYPE)));
      43             :   int offset = 0;
      44             :   int minimum_size = 0;
      45        5096 :   switch (data_index) {
      46             :     case 1:
      47             :       offset = DataHandler::kData1Offset;
      48             :       minimum_size = DataHandler::kSizeWithData1;
      49             :       break;
      50             :     case 2:
      51             :       offset = DataHandler::kData2Offset;
      52             :       minimum_size = DataHandler::kSizeWithData2;
      53        2072 :       break;
      54             :     case 3:
      55             :       offset = DataHandler::kData3Offset;
      56             :       minimum_size = DataHandler::kSizeWithData3;
      57        1456 :       break;
      58             :     default:
      59           0 :       UNREACHABLE();
      60             :       break;
      61             :   }
      62             :   USE(minimum_size);
      63             :   CSA_ASSERT(this, UintPtrGreaterThanOrEqual(
      64             :                        LoadMapInstanceSizeInWords(handler_map),
      65             :                        IntPtrConstant(minimum_size / kTaggedSize)));
      66       10192 :   return LoadMaybeWeakObjectField(handler, offset);
      67             : }
      68             : 
      69         504 : TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
      70             :     Node* slot, Node* vector, Node* receiver_map, Label* if_handler,
      71             :     TVariable<MaybeObject>* var_handler, Label* if_miss) {
      72         504 :   Comment("TryMonomorphicCase");
      73             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
      74             : 
      75             :   // TODO(ishell): add helper class that hides offset computations for a series
      76             :   // of loads.
      77             :   CSA_ASSERT(this, IsFeedbackVector(vector), vector);
      78             :   int32_t header_size = FeedbackVector::kFeedbackSlotsOffset - kHeapObjectTag;
      79             :   // Adding |header_size| with a separate IntPtrAdd rather than passing it
      80             :   // into ElementOffsetFromIndex() allows it to be folded into a single
      81             :   // [base, index, offset] indirect memory access on x64.
      82        1008 :   Node* offset = ElementOffsetFromIndex(slot, HOLEY_ELEMENTS, SMI_PARAMETERS);
      83             :   TNode<MaybeObject> feedback = ReinterpretCast<MaybeObject>(
      84             :       Load(MachineType::AnyTagged(), vector,
      85        1512 :            IntPtrAdd(offset, IntPtrConstant(header_size))));
      86             : 
      87             :   // Try to quickly handle the monomorphic case without knowing for sure
      88             :   // if we have a weak reference in feedback.
      89        1008 :   GotoIf(IsNotWeakReferenceTo(feedback, CAST(receiver_map)), if_miss);
      90             : 
      91             :   TNode<MaybeObject> handler = UncheckedCast<MaybeObject>(
      92             :       Load(MachineType::AnyTagged(), vector,
      93        1512 :            IntPtrAdd(offset, IntPtrConstant(header_size + kTaggedSize))));
      94             : 
      95             :   *var_handler = handler;
      96         504 :   Goto(if_handler);
      97         504 :   return feedback;
      98             : }
      99             : 
     100         616 : void AccessorAssembler::HandlePolymorphicCase(
     101             :     Node* receiver_map, TNode<WeakFixedArray> feedback, Label* if_handler,
     102             :     TVariable<MaybeObject>* var_handler, Label* if_miss,
     103             :     int min_feedback_capacity) {
     104         616 :   Comment("HandlePolymorphicCase");
     105             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
     106             : 
     107             :   // Deferred so the unrolled case can omit frame construction in bytecode
     108             :   // handler.
     109             :   Label loop(this, Label::kDeferred);
     110             : 
     111             :   // Iterate {feedback} array.
     112             :   const int kEntrySize = 2;
     113             : 
     114             :   // Loading feedback's length is delayed until we need it when looking past
     115             :   // the first {min_feedback_capacity} (map, handler) pairs.
     116             :   Node* length = nullptr;
     117             :   CSA_ASSERT(this, SmiGreaterThanOrEqual(
     118             :                        LoadWeakFixedArrayLength(feedback),
     119             :                        SmiConstant(min_feedback_capacity * kEntrySize)));
     120             : 
     121             :   const int kUnrolledIterations = IC::kMaxPolymorphicMapCount;
     122        3080 :   for (int i = 0; i < kUnrolledIterations; i++) {
     123        2464 :     int map_index = i * kEntrySize;
     124        2464 :     int handler_index = i * kEntrySize + 1;
     125             : 
     126        2464 :     if (i >= min_feedback_capacity) {
     127        1960 :       if (length == nullptr) length = LoadWeakFixedArrayLength(feedback);
     128        1344 :       GotoIf(SmiGreaterThanOrEqual(SmiConstant(handler_index), CAST(length)),
     129        2688 :              if_miss);
     130             :     }
     131             : 
     132             :     Label next_entry(this);
     133             :     TNode<MaybeObject> maybe_cached_map =
     134        2464 :         LoadWeakFixedArrayElement(feedback, map_index);
     135             :     CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
     136             :     GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
     137        4928 :            &next_entry);
     138             : 
     139             :     // Found, now call handler.
     140             :     TNode<MaybeObject> handler =
     141        2464 :         LoadWeakFixedArrayElement(feedback, handler_index);
     142             :     *var_handler = handler;
     143        2464 :     Goto(if_handler);
     144             : 
     145        2464 :     BIND(&next_entry);
     146        2464 :   }
     147         616 :   Goto(&loop);
     148             : 
     149             :   // Loop from {kUnrolledIterations}*kEntrySize to {length}.
     150         616 :   BIND(&loop);
     151        1232 :   Node* start_index = IntPtrConstant(kUnrolledIterations * kEntrySize);
     152        1232 :   Node* end_index = LoadAndUntagWeakFixedArrayLength(feedback);
     153             :   BuildFastLoop(
     154             :       start_index, end_index,
     155         616 :       [this, receiver_map, feedback, if_handler, var_handler](Node* index) {
     156         616 :         Label next_entry(this);
     157             :         TNode<MaybeObject> maybe_cached_map =
     158         616 :             LoadWeakFixedArrayElement(feedback, index);
     159             :         CSA_ASSERT(this, IsWeakOrCleared(maybe_cached_map));
     160         616 :         GotoIf(IsNotWeakReferenceTo(maybe_cached_map, CAST(receiver_map)),
     161        1232 :                &next_entry);
     162             : 
     163             :         // Found, now call handler.
     164             :         TNode<MaybeObject> handler =
     165         616 :             LoadWeakFixedArrayElement(feedback, index, kTaggedSize);
     166         616 :         *var_handler = handler;
     167         616 :         Goto(if_handler);
     168             : 
     169         616 :         BIND(&next_entry);
     170         616 :       },
     171        1848 :       kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
     172             :   // The loop falls through if no handler was found.
     173         616 :   Goto(if_miss);
     174         616 : }
     175             : 
     176        1288 : void AccessorAssembler::HandleLoadICHandlerCase(
     177             :     const LoadICParameters* p, TNode<Object> handler, Label* miss,
     178             :     ExitPoint* exit_point, ICMode ic_mode, OnNonExistent on_nonexistent,
     179             :     ElementSupport support_elements) {
     180        1288 :   Comment("have_handler");
     181             : 
     182        1288 :   VARIABLE(var_holder, MachineRepresentation::kTagged, p->holder);
     183        2576 :   VARIABLE(var_smi_handler, MachineRepresentation::kTagged, handler);
     184             : 
     185        1288 :   Variable* vars[] = {&var_holder, &var_smi_handler};
     186        2576 :   Label if_smi_handler(this, 2, vars);
     187        1288 :   Label try_proto_handler(this, Label::kDeferred),
     188        1288 :       call_handler(this, Label::kDeferred);
     189             : 
     190        2576 :   Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler);
     191             : 
     192             :   // |handler| is a Smi, encoding what to do. See SmiHandler methods
     193             :   // for the encoding format.
     194        1288 :   BIND(&if_smi_handler);
     195             :   {
     196             :     HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(),
     197             :                                handler, miss, exit_point, on_nonexistent,
     198        2576 :                                support_elements);
     199             :   }
     200             : 
     201        1288 :   BIND(&try_proto_handler);
     202             :   {
     203        3864 :     GotoIf(IsCodeMap(LoadMap(CAST(handler))), &call_handler);
     204             :     HandleLoadICProtoHandler(p, handler, &var_holder, &var_smi_handler,
     205        1288 :                              &if_smi_handler, miss, exit_point, ic_mode);
     206             :   }
     207             : 
     208        1288 :   BIND(&call_handler);
     209             :   {
     210             :     exit_point->ReturnCallStub(LoadWithVectorDescriptor{}, handler, p->context,
     211        3864 :                                p->receiver, p->name, p->slot, p->vector);
     212        1288 :   }
     213        1288 : }
     214             : 
     215        1288 : void AccessorAssembler::HandleLoadCallbackProperty(const LoadICParameters* p,
     216             :                                                    TNode<JSObject> holder,
     217             :                                                    TNode<WordT> handler_word,
     218             :                                                    ExitPoint* exit_point) {
     219        1288 :   Comment("native_data_property_load");
     220             :   TNode<IntPtrT> descriptor =
     221        1288 :       Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
     222             : 
     223             :   Label runtime(this, Label::kDeferred);
     224        1288 :   Callable callable = CodeFactory::ApiGetter(isolate());
     225             :   TNode<AccessorInfo> accessor_info =
     226        2576 :       CAST(LoadDescriptorValue(LoadMap(holder), descriptor));
     227             : 
     228        2576 :   GotoIf(IsRuntimeCallStatsEnabled(), &runtime);
     229             :   exit_point->ReturnCallStub(callable, p->context, p->receiver, holder,
     230        1288 :                              accessor_info);
     231             : 
     232        1288 :   BIND(&runtime);
     233             :   exit_point->ReturnCallRuntime(Runtime::kLoadCallbackProperty, p->context,
     234        2576 :                                 p->receiver, holder, accessor_info, p->name);
     235        1288 : }
     236             : 
     237        1288 : void AccessorAssembler::HandleLoadAccessor(
     238             :     const LoadICParameters* p, TNode<CallHandlerInfo> call_handler_info,
     239             :     TNode<WordT> handler_word, TNode<DataHandler> handler,
     240             :     TNode<IntPtrT> handler_kind, ExitPoint* exit_point) {
     241        1288 :   Comment("api_getter");
     242             :   Label runtime(this, Label::kDeferred);
     243             :   // Context is stored either in data2 or data3 field depending on whether
     244             :   // the access check is enabled for this handler or not.
     245             :   TNode<MaybeObject> maybe_context = Select<MaybeObject>(
     246        1288 :       IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
     247        1288 :       [=] { return LoadHandlerDataField(handler, 3); },
     248        3864 :       [=] { return LoadHandlerDataField(handler, 2); });
     249             : 
     250             :   CSA_ASSERT(this, IsWeakOrCleared(maybe_context));
     251        1288 :   CSA_CHECK(this, IsNotCleared(maybe_context));
     252        2576 :   TNode<Object> context = GetHeapObjectAssumeWeak(maybe_context);
     253             : 
     254        2576 :   GotoIf(IsRuntimeCallStatsEnabled(), &runtime);
     255             :   {
     256             :     TNode<Foreign> foreign = CAST(
     257             :         LoadObjectField(call_handler_info, CallHandlerInfo::kJsCallbackOffset));
     258             :     TNode<WordT> callback = TNode<WordT>::UncheckedCast(LoadObjectField(
     259        1288 :         foreign, Foreign::kForeignAddressOffset, MachineType::Pointer()));
     260             :     TNode<Object> data =
     261        1288 :         LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset);
     262             : 
     263        1288 :     VARIABLE(api_holder, MachineRepresentation::kTagged, p->receiver);
     264        1288 :     Label load(this);
     265        2576 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)),
     266        2576 :            &load);
     267             : 
     268             :     CSA_ASSERT(
     269             :         this,
     270             :         WordEqual(handler_kind,
     271             :                   IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype)));
     272             : 
     273        5152 :     api_holder.Bind(LoadMapPrototype(LoadMap(p->receiver)));
     274        1288 :     Goto(&load);
     275             : 
     276        1288 :     BIND(&load);
     277        1288 :     Callable callable = CodeFactory::CallApiCallback(isolate());
     278        1288 :     TNode<IntPtrT> argc = IntPtrConstant(0);
     279             :     exit_point->Return(CallStub(callable, nullptr, context, callback, argc,
     280        5152 :                                 data, api_holder.value(), p->receiver));
     281             :   }
     282             : 
     283        1288 :   BIND(&runtime);
     284             :   exit_point->ReturnCallRuntime(Runtime::kLoadAccessorProperty, context,
     285             :                                 p->receiver, SmiTag(handler_kind),
     286        1288 :                                 call_handler_info);
     287        1288 : }
     288             : 
     289        1288 : void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word,
     290             :                                         Variable* var_double_value,
     291             :                                         Label* rebox_double,
     292             :                                         ExitPoint* exit_point) {
     293        1288 :   Comment("field_load");
     294        1288 :   Node* index = DecodeWord<LoadHandler::FieldIndexBits>(handler_word);
     295        3864 :   Node* offset = IntPtrMul(index, IntPtrConstant(kTaggedSize));
     296             : 
     297        1288 :   Label inobject(this), out_of_object(this);
     298             :   Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject,
     299        1288 :          &out_of_object);
     300             : 
     301        1288 :   BIND(&inobject);
     302             :   {
     303             :     Label is_double(this);
     304        1288 :     GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
     305        1288 :     exit_point->Return(LoadObjectField(holder, offset));
     306             : 
     307        1288 :     BIND(&is_double);
     308             :     if (FLAG_unbox_double_fields) {
     309             :       var_double_value->Bind(
     310        1288 :           LoadObjectField(holder, offset, MachineType::Float64()));
     311             :     } else {
     312             :       Node* mutable_heap_number = LoadObjectField(holder, offset);
     313             :       var_double_value->Bind(LoadHeapNumberValue(mutable_heap_number));
     314             :     }
     315        1288 :     Goto(rebox_double);
     316             :   }
     317             : 
     318        1288 :   BIND(&out_of_object);
     319             :   {
     320             :     Label is_double(this);
     321        2576 :     Node* properties = LoadFastProperties(holder);
     322             :     Node* value = LoadObjectField(properties, offset);
     323        1288 :     GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double);
     324        1288 :     exit_point->Return(value);
     325             : 
     326        1288 :     BIND(&is_double);
     327        2576 :     var_double_value->Bind(LoadHeapNumberValue(value));
     328        1288 :     Goto(rebox_double);
     329        1288 :   }
     330        1288 : }
     331             : 
     332           0 : TNode<Object> AccessorAssembler::LoadDescriptorValue(
     333             :     TNode<Map> map, TNode<IntPtrT> descriptor_entry) {
     334        4536 :   return CAST(LoadDescriptorValueOrFieldType(map, descriptor_entry));
     335             : }
     336             : 
     337        4704 : TNode<MaybeObject> AccessorAssembler::LoadDescriptorValueOrFieldType(
     338             :     TNode<Map> map, TNode<IntPtrT> descriptor_entry) {
     339        4704 :   TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
     340        4704 :   return LoadFieldTypeByDescriptorEntry(descriptors, descriptor_entry);
     341             : }
     342             : 
     343        1288 : void AccessorAssembler::HandleLoadICSmiHandlerCase(
     344             :     const LoadICParameters* p, Node* holder, SloppyTNode<Smi> smi_handler,
     345             :     SloppyTNode<Object> handler, Label* miss, ExitPoint* exit_point,
     346             :     OnNonExistent on_nonexistent, ElementSupport support_elements) {
     347        1288 :   VARIABLE(var_double_value, MachineRepresentation::kFloat64);
     348        1288 :   Label rebox_double(this, &var_double_value);
     349             : 
     350        2576 :   TNode<WordT> handler_word = SmiUntag(smi_handler);
     351             :   TNode<IntPtrT> handler_kind =
     352             :       Signed(DecodeWord<LoadHandler::KindBits>(handler_word));
     353        1288 :   if (support_elements == kSupportElements) {
     354          56 :     Label if_element(this), if_indexed_string(this), if_property(this);
     355         112 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kElement)),
     356         112 :            &if_element);
     357         112 :     Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kIndexedString)),
     358         112 :            &if_indexed_string, &if_property);
     359             : 
     360          56 :     BIND(&if_element);
     361          56 :     Comment("element_load");
     362         112 :     Node* intptr_index = TryToIntptr(p->name, miss);
     363             :     Node* elements = LoadElements(holder);
     364             :     Node* is_jsarray_condition =
     365             :         IsSetWord<LoadHandler::IsJsArrayBits>(handler_word);
     366             :     Node* elements_kind =
     367         112 :         DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word);
     368          56 :     Label if_hole(this), unimplemented_elements_kind(this),
     369          56 :         if_oob(this, Label::kDeferred);
     370             :     EmitElementLoad(holder, elements, elements_kind, intptr_index,
     371             :                     is_jsarray_condition, &if_hole, &rebox_double,
     372             :                     &var_double_value, &unimplemented_elements_kind, &if_oob,
     373          56 :                     miss, exit_point);
     374             : 
     375          56 :     BIND(&unimplemented_elements_kind);
     376             :     {
     377             :       // Smi handlers should only be installed for supported elements kinds.
     378             :       // Crash if we get here.
     379          56 :       DebugBreak();
     380          56 :       Goto(miss);
     381             :     }
     382             : 
     383          56 :     BIND(&if_oob);
     384             :     {
     385          56 :       Comment("out of bounds elements access");
     386             :       Label return_undefined(this);
     387             : 
     388             :       // Check if we're allowed to handle OOB accesses.
     389             :       Node* allow_out_of_bounds =
     390             :           IsSetWord<LoadHandler::AllowOutOfBoundsBits>(handler_word);
     391          56 :       GotoIfNot(allow_out_of_bounds, miss);
     392             : 
     393             :       // Negative indices aren't valid array indices (according to
     394             :       // the ECMAScript specification), and are stored as properties
     395             :       // in V8, not elements. So we cannot handle them here, except
     396             :       // in case of typed arrays, where integer indexed properties
     397             :       // aren't looked up in the prototype chain.
     398         112 :       GotoIf(IsJSTypedArray(holder), &return_undefined);
     399         168 :       GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), miss);
     400             : 
     401             :       // For all other receivers we need to check that the prototype chain
     402             :       // doesn't contain any elements.
     403          56 :       BranchIfPrototypesHaveNoElements(LoadMap(holder), &return_undefined,
     404         112 :                                        miss);
     405             : 
     406          56 :       BIND(&return_undefined);
     407         112 :       exit_point->Return(UndefinedConstant());
     408             :     }
     409             : 
     410          56 :     BIND(&if_hole);
     411             :     {
     412          56 :       Comment("convert hole");
     413          56 :       GotoIfNot(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss);
     414         112 :       GotoIf(IsNoElementsProtectorCellInvalid(), miss);
     415         112 :       exit_point->Return(UndefinedConstant());
     416             :     }
     417             : 
     418          56 :     BIND(&if_indexed_string);
     419             :     {
     420             :       Label if_oob(this, Label::kDeferred);
     421             : 
     422          56 :       Comment("indexed string");
     423         112 :       Node* intptr_index = TryToIntptr(p->name, miss);
     424         112 :       Node* length = LoadStringLengthAsWord(holder);
     425         112 :       GotoIf(UintPtrGreaterThanOrEqual(intptr_index, length), &if_oob);
     426          56 :       TNode<Int32T> code = StringCharCodeAt(holder, intptr_index);
     427          56 :       TNode<String> result = StringFromSingleCharCode(code);
     428          56 :       Return(result);
     429             : 
     430          56 :       BIND(&if_oob);
     431             :       Node* allow_out_of_bounds =
     432             :           IsSetWord<LoadHandler::AllowOutOfBoundsBits>(handler_word);
     433          56 :       GotoIfNot(allow_out_of_bounds, miss);
     434         112 :       GotoIf(IsNoElementsProtectorCellInvalid(), miss);
     435         112 :       Return(UndefinedConstant());
     436             :     }
     437             : 
     438          56 :     BIND(&if_property);
     439         112 :     Comment("property_load");
     440             :   }
     441             : 
     442        1288 :   Label constant(this), field(this), normal(this, Label::kDeferred),
     443        1288 :       interceptor(this, Label::kDeferred), nonexistent(this),
     444        1288 :       accessor(this, Label::kDeferred), global(this, Label::kDeferred),
     445        1288 :       module_export(this, Label::kDeferred), proxy(this, Label::kDeferred),
     446        1288 :       native_data_property(this), api_getter(this);
     447        3864 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
     448             : 
     449        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
     450        2576 :          &constant);
     451             : 
     452        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
     453        2576 :          &nonexistent);
     454             : 
     455        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)),
     456        2576 :          &normal);
     457             : 
     458        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kAccessor)),
     459        2576 :          &accessor);
     460             : 
     461             :   GotoIf(
     462        2576 :       WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNativeDataProperty)),
     463        2576 :       &native_data_property);
     464             : 
     465        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kApiGetter)),
     466        2576 :          &api_getter);
     467             : 
     468             :   GotoIf(WordEqual(handler_kind,
     469        2576 :                    IntPtrConstant(LoadHandler::kApiGetterHolderIsPrototype)),
     470        2576 :          &api_getter);
     471             : 
     472        2576 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kGlobal)),
     473        2576 :          &global);
     474             : 
     475        3864 :   GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kProxy)), &proxy);
     476             : 
     477        2576 :   Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kModuleExport)),
     478        2576 :          &module_export, &interceptor);
     479             : 
     480        1288 :   BIND(&field);
     481             :   HandleLoadField(holder, handler_word, &var_double_value, &rebox_double,
     482        1288 :                   exit_point);
     483             : 
     484        1288 :   BIND(&nonexistent);
     485             :   // This is a handler for a load of a non-existent value.
     486        1288 :   if (on_nonexistent == OnNonExistent::kThrowReferenceError) {
     487             :     exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
     488         392 :                                   p->name);
     489             :   } else {
     490             :     DCHECK_EQ(OnNonExistent::kReturnUndefined, on_nonexistent);
     491        1792 :     exit_point->Return(UndefinedConstant());
     492             :   }
     493             : 
     494        1288 :   BIND(&constant);
     495             :   {
     496        1288 :     Comment("constant_load");
     497             :     TNode<IntPtrT> descriptor =
     498             :         Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
     499        2576 :     Node* value = LoadDescriptorValue(LoadMap(holder), descriptor);
     500             : 
     501        1288 :     exit_point->Return(value);
     502             :   }
     503             : 
     504        1288 :   BIND(&normal);
     505             :   {
     506        1288 :     Comment("load_normal");
     507        1288 :     TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder));
     508             :     TVARIABLE(IntPtrT, var_name_index);
     509        1288 :     Label found(this, &var_name_index);
     510        1288 :     NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found,
     511        1288 :                                          &var_name_index, miss);
     512        1288 :     BIND(&found);
     513             :     {
     514        1288 :       VARIABLE(var_details, MachineRepresentation::kWord32);
     515        2576 :       VARIABLE(var_value, MachineRepresentation::kTagged);
     516             :       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
     517        1288 :                                      &var_details, &var_value);
     518             :       Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
     519        2576 :                                          p->context, p->receiver, miss);
     520        2576 :       exit_point->Return(value);
     521             :     }
     522             :   }
     523             : 
     524        1288 :   BIND(&accessor);
     525             :   {
     526        1288 :     Comment("accessor_load");
     527             :     TNode<IntPtrT> descriptor =
     528             :         Signed(DecodeWord<LoadHandler::DescriptorBits>(handler_word));
     529        2576 :     Node* accessor_pair = LoadDescriptorValue(LoadMap(holder), descriptor);
     530             :     CSA_ASSERT(this, IsAccessorPair(accessor_pair));
     531             :     Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
     532             :     CSA_ASSERT(this, Word32BinaryNot(IsTheHole(getter)));
     533             : 
     534        1288 :     Callable callable = CodeFactory::Call(isolate());
     535        1288 :     exit_point->Return(CallJS(callable, p->context, getter, p->receiver));
     536             :   }
     537             : 
     538        1288 :   BIND(&native_data_property);
     539        1288 :   HandleLoadCallbackProperty(p, CAST(holder), handler_word, exit_point);
     540             : 
     541        1288 :   BIND(&api_getter);
     542             :   HandleLoadAccessor(p, CAST(holder), handler_word, CAST(handler), handler_kind,
     543        1288 :                      exit_point);
     544             : 
     545        1288 :   BIND(&proxy);
     546             :   {
     547        1288 :     VARIABLE(var_index, MachineType::PointerRepresentation());
     548        2576 :     VARIABLE(var_unique, MachineRepresentation::kTagged);
     549             : 
     550        1288 :     Label if_index(this), if_unique_name(this),
     551        1288 :         to_name_failed(this, Label::kDeferred);
     552             : 
     553        1288 :     if (support_elements == kSupportElements) {
     554             :       DCHECK_NE(on_nonexistent, OnNonExistent::kThrowReferenceError);
     555             : 
     556             :       TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
     557          56 :                 &to_name_failed);
     558             : 
     559          56 :       BIND(&if_unique_name);
     560             :       exit_point->ReturnCallStub(
     561             :           Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
     562             :           p->context, holder, var_unique.value(), p->receiver,
     563         112 :           SmiConstant(on_nonexistent));
     564             : 
     565          56 :       BIND(&if_index);
     566             :       // TODO(mslekova): introduce TryToName that doesn't try to compute
     567             :       // the intptr index value
     568          56 :       Goto(&to_name_failed);
     569             : 
     570          56 :       BIND(&to_name_failed);
     571             :       exit_point->ReturnCallRuntime(Runtime::kGetPropertyWithReceiver,
     572             :                                     p->context, holder, p->name, p->receiver,
     573          56 :                                     SmiConstant(on_nonexistent));
     574             :     } else {
     575             :       exit_point->ReturnCallStub(
     576             :           Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
     577             :           p->context, holder, p->name, p->receiver,
     578        2464 :           SmiConstant(on_nonexistent));
     579        1288 :     }
     580             :   }
     581             : 
     582        1288 :   BIND(&global);
     583             :   {
     584             :     CSA_ASSERT(this, IsPropertyCell(holder));
     585             :     // Ensure the property cell doesn't contain the hole.
     586             :     Node* value = LoadObjectField(holder, PropertyCell::kValueOffset);
     587             :     Node* details =
     588        2576 :         LoadAndUntagToWord32ObjectField(holder, PropertyCell::kDetailsOffset);
     589        2576 :     GotoIf(IsTheHole(value), miss);
     590             : 
     591             :     exit_point->Return(
     592        2576 :         CallGetterIfAccessor(value, details, p->context, p->receiver, miss));
     593             :   }
     594             : 
     595        1288 :   BIND(&interceptor);
     596             :   {
     597        1288 :     Comment("load_interceptor");
     598             :     exit_point->ReturnCallRuntime(Runtime::kLoadPropertyWithInterceptor,
     599             :                                   p->context, p->name, p->receiver, holder,
     600        1288 :                                   p->slot, p->vector);
     601             :   }
     602             : 
     603        1288 :   BIND(&module_export);
     604             :   {
     605        1288 :     Comment("module export");
     606             :     Node* index = DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);
     607             :     Node* module =
     608             :         LoadObjectField(p->receiver, JSModuleNamespace::kModuleOffset,
     609        2576 :                         MachineType::TaggedPointer());
     610        1288 :     TNode<ObjectHashTable> exports = CAST(LoadObjectField(
     611             :         module, Module::kExportsOffset, MachineType::TaggedPointer()));
     612        2576 :     Node* cell = LoadFixedArrayElement(exports, index);
     613             :     // The handler is only installed for exports that exist.
     614             :     CSA_ASSERT(this, IsCell(cell));
     615        1288 :     Node* value = LoadCellValue(cell);
     616             :     Label is_the_hole(this, Label::kDeferred);
     617        2576 :     GotoIf(IsTheHole(value), &is_the_hole);
     618        1288 :     exit_point->Return(value);
     619             : 
     620        1288 :     BIND(&is_the_hole);
     621             :     {
     622             :       Node* message = SmiConstant(MessageTemplate::kNotDefined);
     623             :       exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context,
     624        1288 :                                     message, p->name);
     625        1288 :     }
     626             :   }
     627             : 
     628        1288 :   BIND(&rebox_double);
     629        5152 :   exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value()));
     630        1288 : }
     631             : 
     632             : // Performs actions common to both load and store handlers:
     633             : // 1. Checks prototype validity cell.
     634             : // 2. If |on_code_handler| is provided, then it checks if the sub handler is
     635             : //    a smi or code and if it's a code then it calls |on_code_handler| to
     636             : //    generate a code that handles Code handlers.
     637             : //    If |on_code_handler| is not provided, then only smi sub handler are
     638             : //    expected.
     639             : // 3. Does access check on receiver if ICHandler::DoAccessCheckOnReceiverBits
     640             : //    bit is set in the smi handler.
     641             : // 4. Does dictionary lookup on receiver if ICHandler::LookupOnReceiverBits bit
     642             : //    is set in the smi handler. If |on_found_on_receiver| is provided then
     643             : //    it calls it to generate a code that handles the "found on receiver case"
     644             : //    or just misses if the |on_found_on_receiver| is not provided.
     645             : // 5. Falls through in a case of a smi handler which is returned from this
     646             : //    function (tagged!).
     647             : // TODO(ishell): Remove templatezation once we move common bits from
     648             : // Load/StoreHandler to the base class.
     649             : template <typename ICHandler, typename ICParameters>
     650        1456 : Node* AccessorAssembler::HandleProtoHandler(
     651             :     const ICParameters* p, Node* handler, const OnCodeHandler& on_code_handler,
     652             :     const OnFoundOnReceiver& on_found_on_receiver, Label* miss,
     653             :     ICMode ic_mode) {
     654             :   //
     655             :   // Check prototype validity cell.
     656             :   //
     657             :   {
     658             :     Node* maybe_validity_cell =
     659        1456 :         LoadObjectField(handler, ICHandler::kValidityCellOffset);
     660        1456 :     CheckPrototypeValidityCell(maybe_validity_cell, miss);
     661             :   }
     662             : 
     663             :   //
     664             :   // Check smi handler bits.
     665             :   //
     666             :   {
     667             :     Node* smi_or_code_handler =
     668             :         LoadObjectField(handler, ICHandler::kSmiHandlerOffset);
     669        1456 :     if (on_code_handler) {
     670          56 :       Label if_smi_handler(this);
     671         112 :       GotoIf(TaggedIsSmi(smi_or_code_handler), &if_smi_handler);
     672             : 
     673             :       CSA_ASSERT(this, IsCodeMap(LoadMap(smi_or_code_handler)));
     674          56 :       on_code_handler(smi_or_code_handler);
     675             : 
     676          56 :       BIND(&if_smi_handler);
     677             :     } else {
     678             :       CSA_ASSERT(this, TaggedIsSmi(smi_or_code_handler));
     679             :     }
     680        2912 :     Node* handler_flags = SmiUntag(smi_or_code_handler);
     681             : 
     682             :     // Lookup on receiver and access checks are not necessary for global ICs
     683             :     // because in the former case the validity cell check guards modifications
     684             :     // of the global object and the latter is not applicable to the global
     685             :     // object.
     686             :     int mask = ICHandler::LookupOnReceiverBits::kMask |
     687             :                ICHandler::DoAccessCheckOnReceiverBits::kMask;
     688        1456 :     if (ic_mode == ICMode::kGlobalIC) {
     689             :       CSA_ASSERT(this, IsClearWord(handler_flags, mask));
     690             :     } else {
     691             :       DCHECK_EQ(ICMode::kNonGlobalIC, ic_mode);
     692             : 
     693        1232 :       Label done(this), if_do_access_check(this), if_lookup_on_receiver(this);
     694        1232 :       GotoIf(IsClearWord(handler_flags, mask), &done);
     695             :       // Only one of the bits can be set at a time.
     696             :       CSA_ASSERT(this,
     697             :                  WordNotEqual(WordAnd(handler_flags, IntPtrConstant(mask)),
     698             :                               IntPtrConstant(mask)));
     699         616 :       Branch(IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_flags),
     700         616 :              &if_do_access_check, &if_lookup_on_receiver);
     701             : 
     702         616 :       BIND(&if_do_access_check);
     703             :       {
     704         616 :         TNode<MaybeObject> data2 = LoadHandlerDataField(handler, 2);
     705             :         CSA_ASSERT(this, IsWeakOrCleared(data2));
     706             :         TNode<Object> expected_native_context =
     707        1232 :             GetHeapObjectAssumeWeak(data2, miss);
     708         616 :         EmitAccessCheck(expected_native_context, p->context, p->receiver, &done,
     709             :                         miss);
     710             :       }
     711             : 
     712             :       // Dictionary lookup on receiver is not necessary for Load/StoreGlobalIC
     713             :       // because prototype validity cell check already guards modifications of
     714             :       // the global object.
     715         616 :       BIND(&if_lookup_on_receiver);
     716             :       {
     717             :         DCHECK_EQ(ICMode::kNonGlobalIC, ic_mode);
     718             :         CSA_ASSERT(this, Word32BinaryNot(HasInstanceType(
     719             :                              p->receiver, JS_GLOBAL_OBJECT_TYPE)));
     720             : 
     721             :         TNode<NameDictionary> properties =
     722        1232 :             CAST(LoadSlowProperties(p->receiver));
     723             :         TVARIABLE(IntPtrT, var_name_index);
     724         616 :         Label found(this, &var_name_index);
     725         616 :         NameDictionaryLookup<NameDictionary>(properties, CAST(p->name), &found,
     726             :                                              &var_name_index, &done);
     727         616 :         BIND(&found);
     728             :         {
     729         616 :           if (on_found_on_receiver) {
     730         616 :             on_found_on_receiver(properties, var_name_index.value());
     731             :           } else {
     732           0 :             Goto(miss);
     733             :           }
     734             :         }
     735             :       }
     736             : 
     737        1232 :       BIND(&done);
     738             :     }
     739        1456 :     return smi_or_code_handler;
     740             :   }
     741             : }
     742             : 
     743        1288 : void AccessorAssembler::HandleLoadICProtoHandler(
     744             :     const LoadICParameters* p, Node* handler, Variable* var_holder,
     745             :     Variable* var_smi_handler, Label* if_smi_handler, Label* miss,
     746             :     ExitPoint* exit_point, ICMode ic_mode) {
     747             :   DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep());
     748             :   DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep());
     749             : 
     750             :   Node* smi_handler = HandleProtoHandler<LoadHandler>(
     751             :       p, handler,
     752             :       // Code sub-handlers are not expected in LoadICs, so no |on_code_handler|.
     753             :       nullptr,
     754             :       // on_found_on_receiver
     755         504 :       [=](Node* properties, Node* name_index) {
     756         504 :         VARIABLE(var_details, MachineRepresentation::kWord32);
     757        1008 :         VARIABLE(var_value, MachineRepresentation::kTagged);
     758             :         LoadPropertyFromNameDictionary(properties, name_index, &var_details,
     759         504 :                                        &var_value);
     760             :         Node* value =
     761             :             CallGetterIfAccessor(var_value.value(), var_details.value(),
     762        1008 :                                  p->context, p->receiver, miss);
     763         504 :         exit_point->Return(value);
     764         504 :       },
     765        3864 :       miss, ic_mode);
     766             : 
     767        1288 :   TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
     768             : 
     769        2576 :   Label load_from_cached_holder(this), done(this);
     770             : 
     771        2576 :   Branch(IsStrongReferenceTo(maybe_holder, NullConstant()), &done,
     772        2576 :          &load_from_cached_holder);
     773             : 
     774        1288 :   BIND(&load_from_cached_holder);
     775             :   {
     776             :     // For regular holders, having passed the receiver map check and the
     777             :     // validity cell check implies that |holder| is alive. However, for global
     778             :     // object receivers, |maybe_holder| may be cleared.
     779             :     CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
     780        2576 :     Node* holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
     781             : 
     782        1288 :     var_holder->Bind(holder);
     783        1288 :     Goto(&done);
     784             :   }
     785             : 
     786        1288 :   BIND(&done);
     787             :   {
     788        1288 :     var_smi_handler->Bind(smi_handler);
     789        1288 :     Goto(if_smi_handler);
     790        1288 :   }
     791        1288 : }
     792             : 
     793         616 : void AccessorAssembler::EmitAccessCheck(Node* expected_native_context,
     794             :                                         Node* context, Node* receiver,
     795             :                                         Label* can_access, Label* miss) {
     796             :   CSA_ASSERT(this, IsNativeContext(expected_native_context));
     797             : 
     798        1232 :   Node* native_context = LoadNativeContext(context);
     799        1232 :   GotoIf(WordEqual(expected_native_context, native_context), can_access);
     800             :   // If the receiver is not a JSGlobalProxy then we miss.
     801        1232 :   GotoIfNot(IsJSGlobalProxy(receiver), miss);
     802             :   // For JSGlobalProxy receiver try to compare security tokens of current
     803             :   // and expected native contexts.
     804             :   Node* expected_token = LoadContextElement(expected_native_context,
     805        1232 :                                             Context::SECURITY_TOKEN_INDEX);
     806             :   Node* current_token =
     807        1232 :       LoadContextElement(native_context, Context::SECURITY_TOKEN_INDEX);
     808        1232 :   Branch(WordEqual(expected_token, current_token), can_access, miss);
     809         616 : }
     810             : 
     811        1232 : void AccessorAssembler::JumpIfDataProperty(Node* details, Label* writable,
     812             :                                            Label* readonly) {
     813        1232 :   if (readonly) {
     814             :     // Accessor properties never have the READ_ONLY attribute set.
     815        2240 :     GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
     816        2240 :            readonly);
     817             :   } else {
     818             :     CSA_ASSERT(this, IsNotSetWord32(details,
     819             :                                     PropertyDetails::kAttributesReadOnlyMask));
     820             :   }
     821        1232 :   Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
     822        3696 :   GotoIf(Word32Equal(kind, Int32Constant(kData)), writable);
     823             :   // Fall through if it's an accessor property.
     824        1232 : }
     825             : 
     826         336 : void AccessorAssembler::HandleStoreICNativeDataProperty(
     827             :     const StoreICParameters* p, Node* holder, Node* handler_word) {
     828         336 :   Comment("native_data_property_store");
     829             :   TNode<IntPtrT> descriptor =
     830         336 :       Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
     831         672 :   Node* accessor_info = LoadDescriptorValue(LoadMap(holder), descriptor);
     832         336 :   CSA_CHECK(this, IsAccessorInfo(accessor_info));
     833             : 
     834             :   // TODO(8580): Get the language mode lazily when required to avoid the
     835             :   // computation of GetLanguageMode here. Also make the computation of
     836             :   // language mode not dependent on vector.
     837         336 :   Node* language_mode = GetLanguageMode(p->vector, p->slot);
     838             : 
     839             :   TailCallRuntime(Runtime::kStoreCallbackProperty, p->context, p->receiver,
     840         672 :                   holder, accessor_info, p->name, p->value, language_mode);
     841         336 : }
     842             : 
     843         168 : void AccessorAssembler::HandleStoreICHandlerCase(
     844             :     const StoreICParameters* p, TNode<MaybeObject> handler, Label* miss,
     845             :     ICMode ic_mode, ElementSupport support_elements) {
     846         336 :   Label if_smi_handler(this), if_nonsmi_handler(this);
     847         168 :   Label if_proto_handler(this), if_element_handler(this), call_handler(this),
     848         168 :       store_transition_or_global(this);
     849             : 
     850         336 :   Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler);
     851             : 
     852             :   // |handler| is a Smi, encoding what to do. See SmiHandler methods
     853             :   // for the encoding format.
     854         168 :   BIND(&if_smi_handler);
     855             :   {
     856         168 :     Node* holder = p->receiver;
     857         336 :     Node* handler_word = SmiUntag(CAST(handler));
     858             : 
     859         168 :     Label if_fast_smi(this), if_proxy(this);
     860             : 
     861             :     STATIC_ASSERT(StoreHandler::kGlobalProxy + 1 == StoreHandler::kNormal);
     862             :     STATIC_ASSERT(StoreHandler::kNormal + 1 == StoreHandler::kProxy);
     863             :     STATIC_ASSERT(StoreHandler::kProxy + 1 == StoreHandler::kKindsNumber);
     864             : 
     865             :     Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
     866             :     GotoIf(IntPtrLessThan(handler_kind,
     867         336 :                           IntPtrConstant(StoreHandler::kGlobalProxy)),
     868         336 :            &if_fast_smi);
     869         336 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)),
     870         336 :            &if_proxy);
     871             :     CSA_ASSERT(this,
     872             :                WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal)));
     873         168 :     TNode<NameDictionary> properties = CAST(LoadSlowProperties(holder));
     874             : 
     875             :     TVARIABLE(IntPtrT, var_name_index);
     876         168 :     Label dictionary_found(this, &var_name_index);
     877             :     NameDictionaryLookup<NameDictionary>(
     878         168 :         properties, CAST(p->name), &dictionary_found, &var_name_index, miss);
     879         168 :     BIND(&dictionary_found);
     880             :     {
     881             :       Node* details = LoadDetailsByKeyIndex<NameDictionary>(
     882             :           properties, var_name_index.value());
     883             :       // Check that the property is a writable data property (no accessor).
     884             :       const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
     885             :                                        PropertyDetails::kAttributesReadOnlyMask;
     886             :       STATIC_ASSERT(kData == 0);
     887         336 :       GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
     888             : 
     889             :       StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
     890             :                                            p->value);
     891         168 :       Return(p->value);
     892             :     }
     893             : 
     894         168 :     BIND(&if_fast_smi);
     895             :     {
     896             :       Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
     897             : 
     898         168 :       Label data(this), accessor(this), native_data_property(this);
     899         336 :       GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kAccessor)),
     900         336 :              &accessor);
     901             :       Branch(WordEqual(handler_kind,
     902         336 :                        IntPtrConstant(StoreHandler::kNativeDataProperty)),
     903         336 :              &native_data_property, &data);
     904             : 
     905         168 :       BIND(&accessor);
     906         168 :       HandleStoreAccessor(p, holder, handler_word);
     907             : 
     908         168 :       BIND(&native_data_property);
     909         168 :       HandleStoreICNativeDataProperty(p, holder, handler_word);
     910             : 
     911         168 :       BIND(&data);
     912             :       // Handle non-transitioning field stores.
     913         336 :       HandleStoreICSmiHandlerCase(handler_word, holder, p->value, miss);
     914             :     }
     915             : 
     916         168 :     BIND(&if_proxy);
     917         336 :     HandleStoreToProxy(p, holder, miss, support_elements);
     918             :   }
     919             : 
     920         168 :   BIND(&if_nonsmi_handler);
     921             :   {
     922         336 :     GotoIf(IsWeakOrCleared(handler), &store_transition_or_global);
     923             :     TNode<HeapObject> strong_handler = CAST(handler);
     924         168 :     TNode<Map> handler_map = LoadMap(strong_handler);
     925         336 :     Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
     926             : 
     927         168 :     BIND(&if_proto_handler);
     928             :     {
     929             :       HandleStoreICProtoHandler(p, CAST(strong_handler), miss, ic_mode,
     930         168 :                                 support_elements);
     931             :     }
     932             : 
     933             :     // |handler| is a heap object. Must be code, call it.
     934         168 :     BIND(&call_handler);
     935             :     {
     936             :       TailCallStub(StoreWithVectorDescriptor{}, CAST(strong_handler),
     937         168 :                    CAST(p->context), p->receiver, p->name, p->value, p->slot,
     938         336 :                    p->vector);
     939             :     }
     940             :   }
     941             : 
     942         168 :   BIND(&store_transition_or_global);
     943             :   {
     944             :     // Load value or miss if the {handler} weak cell is cleared.
     945             :     CSA_ASSERT(this, IsWeakOrCleared(handler));
     946             :     TNode<HeapObject> map_or_property_cell =
     947         168 :         GetHeapObjectAssumeWeak(handler, miss);
     948             : 
     949         168 :     Label store_global(this), store_transition(this);
     950         336 :     Branch(IsMap(map_or_property_cell), &store_transition, &store_global);
     951             : 
     952         168 :     BIND(&store_global);
     953             :     {
     954             :       TNode<PropertyCell> property_cell = CAST(map_or_property_cell);
     955             :       ExitPoint direct_exit(this);
     956             :       StoreGlobalIC_PropertyCellCase(property_cell, p->value, &direct_exit,
     957         168 :                                      miss);
     958             :     }
     959         168 :     BIND(&store_transition);
     960             :     {
     961         168 :       TNode<Map> map = CAST(map_or_property_cell);
     962             :       HandleStoreICTransitionMapHandlerCase(p, map, miss,
     963         168 :                                             kCheckPrototypeValidity);
     964         168 :       Return(p->value);
     965         168 :     }
     966         168 :   }
     967         168 : }
     968             : 
     969         448 : void AccessorAssembler::HandleStoreICTransitionMapHandlerCase(
     970             :     const StoreICParameters* p, TNode<Map> transition_map, Label* miss,
     971             :     StoreTransitionMapFlags flags) {
     972             :   DCHECK_EQ(0, flags & ~kStoreTransitionMapFlagsMask);
     973         448 :   if (flags & kCheckPrototypeValidity) {
     974             :     Node* maybe_validity_cell =
     975         392 :         LoadObjectField(transition_map, Map::kPrototypeValidityCellOffset);
     976         392 :     CheckPrototypeValidityCell(maybe_validity_cell, miss);
     977             :   }
     978             : 
     979         448 :   TNode<Uint32T> bitfield3 = LoadMapBitField3(transition_map);
     980             :   CSA_ASSERT(this, IsClearWord32<Map::IsDictionaryMapBit>(bitfield3));
     981         448 :   GotoIf(IsSetWord32<Map::IsDeprecatedBit>(bitfield3), miss);
     982             : 
     983             :   // Load last descriptor details.
     984         896 :   Node* nof = DecodeWordFromWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
     985             :   CSA_ASSERT(this, WordNotEqual(nof, IntPtrConstant(0)));
     986         448 :   TNode<DescriptorArray> descriptors = LoadMapDescriptors(transition_map);
     987             : 
     988         896 :   Node* factor = IntPtrConstant(DescriptorArray::kEntrySize);
     989             :   TNode<IntPtrT> last_key_index = UncheckedCast<IntPtrT>(IntPtrAdd(
     990        1344 :       IntPtrConstant(DescriptorArray::ToKeyIndex(-1)), IntPtrMul(nof, factor)));
     991         448 :   if (flags & kValidateTransitionHandler) {
     992         280 :     TNode<Name> key = LoadKeyByKeyIndex(descriptors, last_key_index);
     993         560 :     GotoIf(WordNotEqual(key, p->name), miss);
     994             :   } else {
     995             :     CSA_ASSERT(this, WordEqual(LoadKeyByKeyIndex(descriptors, last_key_index),
     996             :                                p->name));
     997             :   }
     998         896 :   Node* details = LoadDetailsByKeyIndex(descriptors, last_key_index);
     999         448 :   if (flags & kValidateTransitionHandler) {
    1000             :     // Follow transitions only in the following cases:
    1001             :     // 1) name is a non-private symbol and attributes equal to NONE,
    1002             :     // 2) name is a private symbol and attributes equal to DONT_ENUM.
    1003             :     Label attributes_ok(this);
    1004             :     const int kKindAndAttributesDontDeleteReadOnlyMask =
    1005             :         PropertyDetails::KindField::kMask |
    1006             :         PropertyDetails::kAttributesDontDeleteMask |
    1007             :         PropertyDetails::kAttributesReadOnlyMask;
    1008             :     STATIC_ASSERT(kData == 0);
    1009             :     // Both DontDelete and ReadOnly attributes must not be set and it has to be
    1010             :     // a kData property.
    1011         280 :     GotoIf(IsSetWord32(details, kKindAndAttributesDontDeleteReadOnlyMask),
    1012         560 :            miss);
    1013             : 
    1014             :     // DontEnum attribute is allowed only for private symbols and vice versa.
    1015             :     Branch(Word32Equal(
    1016         280 :                IsSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
    1017        1400 :                IsPrivateSymbol(p->name)),
    1018         560 :            &attributes_ok, miss);
    1019             : 
    1020         280 :     BIND(&attributes_ok);
    1021             :   }
    1022             : 
    1023             :   OverwriteExistingFastDataProperty(p->receiver, transition_map, descriptors,
    1024             :                                     last_key_index, details, p->value, miss,
    1025         448 :                                     true);
    1026         448 : }
    1027             : 
    1028         728 : void AccessorAssembler::CheckFieldType(TNode<DescriptorArray> descriptors,
    1029             :                                        Node* name_index, Node* representation,
    1030             :                                        Node* value, Label* bailout) {
    1031        1456 :   Label r_smi(this), r_double(this), r_heapobject(this), all_fine(this);
    1032             :   // Ignore FLAG_track_fields etc. and always emit code for all checks,
    1033             :   // because this builtin is part of the snapshot and therefore should
    1034             :   // be flag independent.
    1035        1456 :   GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)),
    1036        1456 :          &r_smi);
    1037        1456 :   GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)),
    1038        1456 :          &r_double);
    1039             :   GotoIf(
    1040        1456 :       Word32Equal(representation, Int32Constant(Representation::kHeapObject)),
    1041        1456 :       &r_heapobject);
    1042        1456 :   GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)),
    1043        1456 :          bailout);
    1044             :   CSA_ASSERT(this, Word32Equal(representation,
    1045             :                                Int32Constant(Representation::kTagged)));
    1046         728 :   Goto(&all_fine);
    1047             : 
    1048         728 :   BIND(&r_smi);
    1049        1456 :   { Branch(TaggedIsSmi(value), &all_fine, bailout); }
    1050             : 
    1051         728 :   BIND(&r_double);
    1052             :   {
    1053        1456 :     GotoIf(TaggedIsSmi(value), &all_fine);
    1054        1456 :     Node* value_map = LoadMap(value);
    1055             :     // While supporting mutable HeapNumbers would be straightforward, such
    1056             :     // objects should not end up here anyway.
    1057             :     CSA_ASSERT(this, WordNotEqual(value_map,
    1058             :                                   LoadRoot(RootIndex::kMutableHeapNumberMap)));
    1059        1456 :     Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
    1060             :   }
    1061             : 
    1062         728 :   BIND(&r_heapobject);
    1063             :   {
    1064        1456 :     GotoIf(TaggedIsSmi(value), bailout);
    1065             :     TNode<MaybeObject> field_type = LoadFieldTypeByKeyIndex(
    1066         728 :         descriptors, UncheckedCast<IntPtrT>(name_index));
    1067        1456 :     const Address kNoneType = FieldType::None().ptr();
    1068        1456 :     const Address kAnyType = FieldType::Any().ptr();
    1069             :     DCHECK_NE(static_cast<uint32_t>(kNoneType), kClearedWeakHeapObjectLower32);
    1070             :     DCHECK_NE(static_cast<uint32_t>(kAnyType), kClearedWeakHeapObjectLower32);
    1071             :     // FieldType::None can't hold any value.
    1072         728 :     GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
    1073        2912 :                      IntPtrConstant(kNoneType)),
    1074        1456 :            bailout);
    1075             :     // FieldType::Any can hold any value.
    1076         728 :     GotoIf(WordEqual(BitcastMaybeObjectToWord(field_type),
    1077        2912 :                      IntPtrConstant(kAnyType)),
    1078        1456 :            &all_fine);
    1079             :     // Cleared weak references count as FieldType::None, which can't hold any
    1080             :     // value.
    1081             :     TNode<Map> field_type_map =
    1082         728 :         CAST(GetHeapObjectAssumeWeak(field_type, bailout));
    1083             :     // FieldType::Class(...) performs a map check.
    1084        1456 :     Branch(WordEqual(LoadMap(value), field_type_map), &all_fine, bailout);
    1085             :   }
    1086             : 
    1087        1456 :   BIND(&all_fine);
    1088         728 : }
    1089             : 
    1090         728 : void AccessorAssembler::OverwriteExistingFastDataProperty(
    1091             :     Node* object, Node* object_map, Node* descriptors,
    1092             :     Node* descriptor_name_index, Node* details, Node* value, Label* slow,
    1093             :     bool do_transitioning_store) {
    1094        1456 :   Label done(this), if_field(this), if_descriptor(this);
    1095             : 
    1096             :   CSA_ASSERT(this,
    1097             :              Word32Equal(DecodeWord32<PropertyDetails::KindField>(details),
    1098             :                          Int32Constant(kData)));
    1099             : 
    1100         728 :   Branch(Word32Equal(DecodeWord32<PropertyDetails::LocationField>(details),
    1101        1456 :                      Int32Constant(kField)),
    1102        1456 :          &if_field, &if_descriptor);
    1103             : 
    1104         728 :   BIND(&if_field);
    1105             :   {
    1106             :     if (FLAG_track_constant_fields && !do_transitioning_store) {
    1107             :       // TODO(ishell): Taking the slow path is not necessary if new and old
    1108             :       // values are identical.
    1109             :       GotoIf(Word32Equal(
    1110             :                  DecodeWord32<PropertyDetails::ConstnessField>(details),
    1111             :                  Int32Constant(static_cast<int32_t>(VariableMode::kConst))),
    1112             :              slow);
    1113             :     }
    1114             : 
    1115             :     Node* representation =
    1116             :         DecodeWord32<PropertyDetails::RepresentationField>(details);
    1117             : 
    1118             :     CheckFieldType(CAST(descriptors), descriptor_name_index, representation,
    1119         728 :                    value, slow);
    1120             : 
    1121             :     Node* field_index =
    1122        1456 :         DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
    1123        1456 :     field_index = IntPtrAdd(field_index,
    1124        1456 :                             LoadMapInobjectPropertiesStartInWords(object_map));
    1125        1456 :     Node* instance_size_in_words = LoadMapInstanceSizeInWords(object_map);
    1126             : 
    1127         728 :     Label inobject(this), backing_store(this);
    1128         728 :     Branch(UintPtrLessThan(field_index, instance_size_in_words), &inobject,
    1129        1456 :            &backing_store);
    1130             : 
    1131         728 :     BIND(&inobject);
    1132             :     {
    1133        1456 :       Node* field_offset = TimesTaggedSize(field_index);
    1134         728 :       Label tagged_rep(this), double_rep(this);
    1135             :       Branch(
    1136        1456 :           Word32Equal(representation, Int32Constant(Representation::kDouble)),
    1137        1456 :           &double_rep, &tagged_rep);
    1138         728 :       BIND(&double_rep);
    1139             :       {
    1140        1456 :         Node* double_value = ChangeNumberToFloat64(value);
    1141             :         if (FLAG_unbox_double_fields) {
    1142         728 :           if (do_transitioning_store) {
    1143         448 :             StoreMap(object, object_map);
    1144             :           }
    1145             :           StoreObjectFieldNoWriteBarrier(object, field_offset, double_value,
    1146         728 :                                          MachineRepresentation::kFloat64);
    1147             :         } else {
    1148             :           if (do_transitioning_store) {
    1149             :             Node* mutable_heap_number =
    1150             :                 AllocateMutableHeapNumberWithValue(double_value);
    1151             :             StoreMap(object, object_map);
    1152             :             StoreObjectField(object, field_offset, mutable_heap_number);
    1153             :           } else {
    1154             :             Node* mutable_heap_number = LoadObjectField(object, field_offset);
    1155             :             StoreHeapNumberValue(mutable_heap_number, double_value);
    1156             :           }
    1157             :         }
    1158         728 :         Goto(&done);
    1159             :       }
    1160             : 
    1161         728 :       BIND(&tagged_rep);
    1162             :       {
    1163         728 :         if (do_transitioning_store) {
    1164         448 :           StoreMap(object, object_map);
    1165             :         }
    1166         728 :         StoreObjectField(object, field_offset, value);
    1167         728 :         Goto(&done);
    1168         728 :       }
    1169             :     }
    1170             : 
    1171         728 :     BIND(&backing_store);
    1172             :     {
    1173             :       Node* backing_store_index =
    1174        1456 :           IntPtrSub(field_index, instance_size_in_words);
    1175             : 
    1176         728 :       if (do_transitioning_store) {
    1177             :         // Allocate mutable heap number before extending properties backing
    1178             :         // store to ensure that heap verifier will not see the heap in
    1179             :         // inconsistent state.
    1180         448 :         VARIABLE(var_value, MachineRepresentation::kTagged, value);
    1181             :         {
    1182             :           Label cont(this);
    1183             :           GotoIf(Word32NotEqual(representation,
    1184         896 :                                 Int32Constant(Representation::kDouble)),
    1185         896 :                  &cont);
    1186             :           {
    1187         896 :             Node* double_value = ChangeNumberToFloat64(value);
    1188             :             Node* mutable_heap_number =
    1189         896 :                 AllocateMutableHeapNumberWithValue(double_value);
    1190         448 :             var_value.Bind(mutable_heap_number);
    1191         448 :             Goto(&cont);
    1192             :           }
    1193         448 :           BIND(&cont);
    1194             :         }
    1195             : 
    1196             :         TNode<PropertyArray> properties =
    1197         448 :             CAST(ExtendPropertiesBackingStore(object, backing_store_index));
    1198             :         StorePropertyArrayElement(properties, backing_store_index,
    1199         448 :                                   var_value.value());
    1200         448 :         StoreMap(object, object_map);
    1201         448 :         Goto(&done);
    1202             : 
    1203             :       } else {
    1204         280 :         Label tagged_rep(this), double_rep(this);
    1205         280 :         TNode<PropertyArray> properties = CAST(LoadFastProperties(object));
    1206             :         Branch(
    1207         560 :             Word32Equal(representation, Int32Constant(Representation::kDouble)),
    1208         560 :             &double_rep, &tagged_rep);
    1209         280 :         BIND(&double_rep);
    1210             :         {
    1211             :           Node* mutable_heap_number =
    1212         560 :               LoadPropertyArrayElement(properties, backing_store_index);
    1213         560 :           Node* double_value = ChangeNumberToFloat64(value);
    1214         280 :           StoreHeapNumberValue(mutable_heap_number, double_value);
    1215         280 :           Goto(&done);
    1216             :         }
    1217         280 :         BIND(&tagged_rep);
    1218             :         {
    1219             :           StorePropertyArrayElement(properties, backing_store_index, value);
    1220         280 :           Goto(&done);
    1221         280 :         }
    1222             :       }
    1223         728 :     }
    1224             :   }
    1225             : 
    1226         728 :   BIND(&if_descriptor);
    1227             :   {
    1228             :     // Check that constant matches value.
    1229             :     Node* constant = LoadValueByKeyIndex(
    1230        1456 :         CAST(descriptors), UncheckedCast<IntPtrT>(descriptor_name_index));
    1231        1456 :     GotoIf(WordNotEqual(value, constant), slow);
    1232             : 
    1233         728 :     if (do_transitioning_store) {
    1234         448 :       StoreMap(object, object_map);
    1235             :     }
    1236         728 :     Goto(&done);
    1237             :   }
    1238        1456 :   BIND(&done);
    1239         728 : }
    1240             : 
    1241        1848 : void AccessorAssembler::CheckPrototypeValidityCell(Node* maybe_validity_cell,
    1242             :                                                    Label* miss) {
    1243        1848 :   Label done(this);
    1244        3696 :   GotoIf(WordEqual(maybe_validity_cell, SmiConstant(Map::kPrototypeChainValid)),
    1245        1848 :          &done);
    1246             :   CSA_ASSERT(this, TaggedIsNotSmi(maybe_validity_cell));
    1247             : 
    1248        1848 :   Node* cell_value = LoadObjectField(maybe_validity_cell, Cell::kValueOffset);
    1249        3696 :   Branch(WordEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)), &done,
    1250        1848 :          miss);
    1251             : 
    1252        1848 :   BIND(&done);
    1253        1848 : }
    1254             : 
    1255         336 : void AccessorAssembler::HandleStoreAccessor(const StoreICParameters* p,
    1256             :                                             Node* holder, Node* handler_word) {
    1257         336 :   Comment("accessor_store");
    1258             :   TNode<IntPtrT> descriptor =
    1259         336 :       Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
    1260         672 :   Node* accessor_pair = LoadDescriptorValue(LoadMap(holder), descriptor);
    1261             :   CSA_ASSERT(this, IsAccessorPair(accessor_pair));
    1262             :   Node* setter = LoadObjectField(accessor_pair, AccessorPair::kSetterOffset);
    1263             :   CSA_ASSERT(this, Word32BinaryNot(IsTheHole(setter)));
    1264             : 
    1265         336 :   Callable callable = CodeFactory::Call(isolate());
    1266         672 :   Return(CallJS(callable, p->context, setter, p->receiver, p->value));
    1267         336 : }
    1268             : 
    1269         168 : void AccessorAssembler::HandleStoreICProtoHandler(
    1270             :     const StoreICParameters* p, TNode<StoreHandler> handler, Label* miss,
    1271             :     ICMode ic_mode, ElementSupport support_elements) {
    1272         168 :   Comment("HandleStoreICProtoHandler");
    1273             : 
    1274             :   OnCodeHandler on_code_handler;
    1275         168 :   if (support_elements == kSupportElements) {
    1276             :     // Code sub-handlers are expected only in KeyedStoreICs.
    1277         168 :     on_code_handler = [=](Node* code_handler) {
    1278             :       // This is either element store or transitioning element store.
    1279         168 :       Label if_element_store(this), if_transitioning_element_store(this);
    1280         168 :       Branch(IsStoreHandler0Map(LoadMap(handler)), &if_element_store,
    1281         112 :              &if_transitioning_element_store);
    1282          56 :       BIND(&if_element_store);
    1283             :       {
    1284             :         TailCallStub(StoreWithVectorDescriptor{}, code_handler, p->context,
    1285         168 :                      p->receiver, p->name, p->value, p->slot, p->vector);
    1286             :       }
    1287             : 
    1288          56 :       BIND(&if_transitioning_element_store);
    1289             :       {
    1290             :         TNode<MaybeObject> maybe_transition_map =
    1291          56 :             LoadHandlerDataField(handler, 1);
    1292             :         TNode<Map> transition_map =
    1293          56 :             CAST(GetHeapObjectAssumeWeak(maybe_transition_map, miss));
    1294             : 
    1295         168 :         GotoIf(IsDeprecatedMap(transition_map), miss);
    1296             : 
    1297             :         TailCallStub(StoreTransitionDescriptor{}, code_handler, p->context,
    1298             :                      p->receiver, p->name, transition_map, p->value, p->slot,
    1299         168 :                      p->vector);
    1300             :       }
    1301         112 :     };
    1302             :   }
    1303             : 
    1304             :   Node* smi_handler = HandleProtoHandler<StoreHandler>(
    1305             :       p, handler, on_code_handler,
    1306             :       // on_found_on_receiver
    1307         112 :       [=](Node* properties, Node* name_index) {
    1308             :         Node* details =
    1309         112 :             LoadDetailsByKeyIndex<NameDictionary>(properties, name_index);
    1310             :         // Check that the property is a writable data property (no accessor).
    1311             :         const int kTypeAndReadOnlyMask =
    1312             :             PropertyDetails::KindField::kMask |
    1313             :             PropertyDetails::kAttributesReadOnlyMask;
    1314             :         STATIC_ASSERT(kData == 0);
    1315         336 :         GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), miss);
    1316             : 
    1317             :         StoreValueByKeyIndex<NameDictionary>(
    1318         112 :             CAST(properties), UncheckedCast<IntPtrT>(name_index), p->value);
    1319         112 :         Return(p->value);
    1320         112 :       },
    1321         336 :       miss, ic_mode);
    1322             : 
    1323             :   {
    1324         168 :     Label if_add_normal(this), if_store_global_proxy(this), if_api_setter(this),
    1325         168 :         if_accessor(this), if_native_data_property(this);
    1326             : 
    1327             :     CSA_ASSERT(this, TaggedIsSmi(smi_handler));
    1328         336 :     Node* handler_word = SmiUntag(smi_handler);
    1329             : 
    1330             :     Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
    1331         336 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal)),
    1332         336 :            &if_add_normal);
    1333             : 
    1334         168 :     TNode<MaybeObject> maybe_holder = LoadHandlerDataField(handler, 1);
    1335             :     CSA_ASSERT(this, IsWeakOrCleared(maybe_holder));
    1336         336 :     TNode<Object> holder = GetHeapObjectAssumeWeak(maybe_holder, miss);
    1337             : 
    1338         336 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kGlobalProxy)),
    1339         336 :            &if_store_global_proxy);
    1340             : 
    1341         336 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kAccessor)),
    1342         336 :            &if_accessor);
    1343             : 
    1344             :     GotoIf(WordEqual(handler_kind,
    1345         336 :                      IntPtrConstant(StoreHandler::kNativeDataProperty)),
    1346         336 :            &if_native_data_property);
    1347             : 
    1348         336 :     GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kApiSetter)),
    1349         336 :            &if_api_setter);
    1350             : 
    1351             :     GotoIf(WordEqual(handler_kind,
    1352         336 :                      IntPtrConstant(StoreHandler::kApiSetterHolderIsPrototype)),
    1353         336 :            &if_api_setter);
    1354             : 
    1355             :     CSA_ASSERT(this,
    1356             :                WordEqual(handler_kind, IntPtrConstant(StoreHandler::kProxy)));
    1357         168 :     HandleStoreToProxy(p, holder, miss, support_elements);
    1358             : 
    1359         168 :     BIND(&if_add_normal);
    1360             :     {
    1361             :       // This is a case of "transitioning store" to a dictionary mode object
    1362             :       // when the property is still does not exist. The "existing property"
    1363             :       // case is covered above by LookupOnReceiver bit handling of the smi
    1364             :       // handler.
    1365             :       Label slow(this);
    1366         336 :       TNode<Map> receiver_map = LoadMap(p->receiver);
    1367         168 :       InvalidateValidityCellIfPrototype(receiver_map);
    1368             : 
    1369         336 :       TNode<NameDictionary> properties = CAST(LoadSlowProperties(p->receiver));
    1370         168 :       Add<NameDictionary>(properties, CAST(p->name), p->value, &slow);
    1371         168 :       Return(p->value);
    1372             : 
    1373         168 :       BIND(&slow);
    1374             :       TailCallRuntime(Runtime::kAddDictionaryProperty, p->context, p->receiver,
    1375         336 :                       p->name, p->value);
    1376             :     }
    1377             : 
    1378         168 :     BIND(&if_accessor);
    1379         168 :     HandleStoreAccessor(p, holder, handler_word);
    1380             : 
    1381         168 :     BIND(&if_native_data_property);
    1382         168 :     HandleStoreICNativeDataProperty(p, holder, handler_word);
    1383             : 
    1384         168 :     BIND(&if_api_setter);
    1385             :     {
    1386         168 :       Comment("api_setter");
    1387             :       CSA_ASSERT(this, TaggedIsNotSmi(handler));
    1388             :       Node* call_handler_info = holder;
    1389             : 
    1390             :       // Context is stored either in data2 or data3 field depending on whether
    1391             :       // the access check is enabled for this handler or not.
    1392             :       TNode<MaybeObject> maybe_context = Select<MaybeObject>(
    1393             :           IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
    1394         168 :           [=] { return LoadHandlerDataField(handler, 3); },
    1395         504 :           [=] { return LoadHandlerDataField(handler, 2); });
    1396             : 
    1397             :       CSA_ASSERT(this, IsWeakOrCleared(maybe_context));
    1398             :       TNode<Object> context = Select<Object>(
    1399         168 :           IsCleared(maybe_context), [=] { return SmiConstant(0); },
    1400         504 :           [=] { return GetHeapObjectAssumeWeak(maybe_context); });
    1401             : 
    1402             :       Node* foreign = LoadObjectField(call_handler_info,
    1403             :                                       CallHandlerInfo::kJsCallbackOffset);
    1404             :       Node* callback = LoadObjectField(foreign, Foreign::kForeignAddressOffset,
    1405         168 :                                        MachineType::Pointer());
    1406             :       Node* data =
    1407             :           LoadObjectField(call_handler_info, CallHandlerInfo::kDataOffset);
    1408             : 
    1409         168 :       VARIABLE(api_holder, MachineRepresentation::kTagged, p->receiver);
    1410         168 :       Label store(this);
    1411         336 :       GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kApiSetter)),
    1412         336 :              &store);
    1413             : 
    1414             :       CSA_ASSERT(
    1415             :           this,
    1416             :           WordEqual(handler_kind,
    1417             :                     IntPtrConstant(StoreHandler::kApiSetterHolderIsPrototype)));
    1418             : 
    1419         672 :       api_holder.Bind(LoadMapPrototype(LoadMap(p->receiver)));
    1420         168 :       Goto(&store);
    1421             : 
    1422         168 :       BIND(&store);
    1423         168 :       Callable callable = CodeFactory::CallApiCallback(isolate());
    1424         168 :       TNode<IntPtrT> argc = IntPtrConstant(1);
    1425             :       Return(CallStub(callable, nullptr, context, callback, argc, data,
    1426         672 :                       api_holder.value(), p->receiver, p->value));
    1427             :     }
    1428             : 
    1429         168 :     BIND(&if_store_global_proxy);
    1430             :     {
    1431             :       ExitPoint direct_exit(this);
    1432         168 :       StoreGlobalIC_PropertyCellCase(holder, p->value, &direct_exit, miss);
    1433         168 :     }
    1434             :   }
    1435         168 : }
    1436             : 
    1437         672 : Node* AccessorAssembler::GetLanguageMode(Node* vector, Node* slot) {
    1438        1344 :   VARIABLE(var_language_mode, MachineRepresentation::kTaggedSigned,
    1439             :            SmiConstant(LanguageMode::kStrict));
    1440         672 :   Label language_mode_determined(this);
    1441         672 :   BranchIfStrictMode(vector, slot, &language_mode_determined);
    1442         672 :   var_language_mode.Bind(SmiConstant(LanguageMode::kSloppy));
    1443         672 :   Goto(&language_mode_determined);
    1444         672 :   BIND(&language_mode_determined);
    1445        1344 :   return var_language_mode.value();
    1446             : }
    1447             : 
    1448         336 : void AccessorAssembler::HandleStoreToProxy(const StoreICParameters* p,
    1449             :                                            Node* proxy, Label* miss,
    1450             :                                            ElementSupport support_elements) {
    1451         336 :   VARIABLE(var_index, MachineType::PointerRepresentation());
    1452         672 :   VARIABLE(var_unique, MachineRepresentation::kTagged);
    1453             : 
    1454         336 :   Label if_index(this), if_unique_name(this),
    1455         336 :       to_name_failed(this, Label::kDeferred);
    1456             : 
    1457             :   // TODO(8580): Get the language mode lazily when required to avoid the
    1458             :   // computation of GetLanguageMode here. Also make the computation of
    1459             :   // language mode not dependent on vector.
    1460         336 :   Node* language_mode = GetLanguageMode(p->vector, p->slot);
    1461             : 
    1462         336 :   if (support_elements == kSupportElements) {
    1463             :     TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
    1464         112 :               &to_name_failed);
    1465             : 
    1466         112 :     BIND(&if_unique_name);
    1467             :     CallBuiltin(Builtins::kProxySetProperty, p->context, proxy,
    1468         224 :                 var_unique.value(), p->value, p->receiver, language_mode);
    1469         112 :     Return(p->value);
    1470             : 
    1471             :     // The index case is handled earlier by the runtime.
    1472         112 :     BIND(&if_index);
    1473             :     // TODO(mslekova): introduce TryToName that doesn't try to compute
    1474             :     // the intptr index value
    1475         112 :     Goto(&to_name_failed);
    1476             : 
    1477         112 :     BIND(&to_name_failed);
    1478             :     TailCallRuntime(Runtime::kSetPropertyWithReceiver, p->context, proxy,
    1479         224 :                     p->name, p->value, p->receiver, language_mode);
    1480             :   } else {
    1481         672 :     Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
    1482             :     TailCallBuiltin(Builtins::kProxySetProperty, p->context, proxy, name,
    1483         448 :                     p->value, p->receiver, language_mode);
    1484         336 :   }
    1485         336 : }
    1486             : 
    1487         168 : void AccessorAssembler::HandleStoreICSmiHandlerCase(Node* handler_word,
    1488             :                                                     Node* holder, Node* value,
    1489             :                                                     Label* miss) {
    1490         168 :   Comment("field store");
    1491             : #ifdef DEBUG
    1492             :   Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word);
    1493             :   if (FLAG_track_constant_fields) {
    1494             :     CSA_ASSERT(
    1495             :         this,
    1496             :         Word32Or(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kField)),
    1497             :                  WordEqual(handler_kind,
    1498             :                            IntPtrConstant(StoreHandler::kConstField))));
    1499             :   } else {
    1500             :     CSA_ASSERT(this,
    1501             :                WordEqual(handler_kind, IntPtrConstant(StoreHandler::kField)));
    1502             :   }
    1503             : #endif
    1504             : 
    1505             :   Node* field_representation =
    1506         168 :       DecodeWord<StoreHandler::FieldRepresentationBits>(handler_word);
    1507             : 
    1508         168 :   Label if_smi_field(this), if_double_field(this), if_heap_object_field(this),
    1509         168 :       if_tagged_field(this);
    1510             : 
    1511         336 :   GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kTagged)),
    1512         336 :          &if_tagged_field);
    1513             :   GotoIf(WordEqual(field_representation,
    1514         336 :                    IntPtrConstant(StoreHandler::kHeapObject)),
    1515         336 :          &if_heap_object_field);
    1516         336 :   GotoIf(WordEqual(field_representation, IntPtrConstant(StoreHandler::kDouble)),
    1517         336 :          &if_double_field);
    1518             :   CSA_ASSERT(this, WordEqual(field_representation,
    1519             :                              IntPtrConstant(StoreHandler::kSmi)));
    1520         168 :   Goto(&if_smi_field);
    1521             : 
    1522         168 :   BIND(&if_tagged_field);
    1523             :   {
    1524         168 :     Comment("store tagged field");
    1525             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(),
    1526         168 :                               value, miss);
    1527             :   }
    1528             : 
    1529         168 :   BIND(&if_double_field);
    1530             :   {
    1531         168 :     Comment("store double field");
    1532             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Double(),
    1533         168 :                               value, miss);
    1534             :   }
    1535             : 
    1536         168 :   BIND(&if_heap_object_field);
    1537             :   {
    1538         168 :     Comment("store heap object field");
    1539             :     HandleStoreFieldAndReturn(handler_word, holder,
    1540         168 :                               Representation::HeapObject(), value, miss);
    1541             :   }
    1542             : 
    1543         168 :   BIND(&if_smi_field);
    1544             :   {
    1545         168 :     Comment("store smi field");
    1546             :     HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(),
    1547         168 :                               value, miss);
    1548         168 :   }
    1549         168 : }
    1550             : 
    1551         672 : void AccessorAssembler::HandleStoreFieldAndReturn(Node* handler_word,
    1552             :                                                   Node* holder,
    1553             :                                                   Representation representation,
    1554             :                                                   Node* value, Label* miss) {
    1555             :   Node* prepared_value =
    1556         672 :       PrepareValueForStore(handler_word, holder, representation, value, miss);
    1557             : 
    1558        1344 :   Label if_inobject(this), if_out_of_object(this);
    1559         672 :   Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject,
    1560         672 :          &if_out_of_object);
    1561             : 
    1562         672 :   BIND(&if_inobject);
    1563             :   {
    1564             :     StoreNamedField(handler_word, holder, true, representation, prepared_value,
    1565         672 :                     miss);
    1566         672 :     Return(value);
    1567             :   }
    1568             : 
    1569         672 :   BIND(&if_out_of_object);
    1570             :   {
    1571             :     StoreNamedField(handler_word, holder, false, representation, prepared_value,
    1572         672 :                     miss);
    1573         672 :     Return(value);
    1574         672 :   }
    1575         672 : }
    1576             : 
    1577         672 : Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder,
    1578             :                                               Representation representation,
    1579             :                                               Node* value, Label* bailout) {
    1580         672 :   if (representation.IsDouble()) {
    1581         168 :     value = TryTaggedToFloat64(value, bailout);
    1582             : 
    1583         504 :   } else if (representation.IsHeapObject()) {
    1584         336 :     GotoIf(TaggedIsSmi(value), bailout);
    1585             : 
    1586             :     Label done(this);
    1587             :     if (FLAG_track_constant_fields) {
    1588             :       // Skip field type check in favor of constant value check when storing
    1589             :       // to constant field.
    1590             :       GotoIf(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
    1591             :                        IntPtrConstant(StoreHandler::kConstField)),
    1592             :              &done);
    1593             :     }
    1594             :     TNode<IntPtrT> descriptor =
    1595         168 :         Signed(DecodeWord<StoreHandler::DescriptorBits>(handler_word));
    1596             :     TNode<MaybeObject> maybe_field_type =
    1597         168 :         LoadDescriptorValueOrFieldType(LoadMap(holder), descriptor);
    1598             : 
    1599         336 :     GotoIf(TaggedIsSmi(maybe_field_type), &done);
    1600             :     // Check that value type matches the field type.
    1601             :     {
    1602         336 :       Node* field_type = GetHeapObjectAssumeWeak(maybe_field_type, bailout);
    1603         336 :       Branch(WordEqual(LoadMap(value), field_type), &done, bailout);
    1604             :     }
    1605         168 :     BIND(&done);
    1606             : 
    1607         336 :   } else if (representation.IsSmi()) {
    1608         336 :     GotoIfNot(TaggedIsSmi(value), bailout);
    1609             : 
    1610             :   } else {
    1611             :     DCHECK(representation.IsTagged());
    1612             :   }
    1613         672 :   return value;
    1614             : }
    1615             : 
    1616         448 : Node* AccessorAssembler::ExtendPropertiesBackingStore(Node* object,
    1617             :                                                       Node* index) {
    1618         448 :   Comment("[ Extend storage");
    1619             : 
    1620             :   ParameterMode mode = OptimalParameterMode();
    1621             : 
    1622             :   // TODO(gsathya): Clean up the type conversions by creating smarter
    1623             :   // helpers that do the correct op based on the mode.
    1624         448 :   VARIABLE(var_properties, MachineRepresentation::kTaggedPointer);
    1625         896 :   VARIABLE(var_encoded_hash, MachineRepresentation::kWord32);
    1626         896 :   VARIABLE(var_length, ParameterRepresentation(mode));
    1627             : 
    1628         448 :   Node* properties = LoadObjectField(object, JSObject::kPropertiesOrHashOffset);
    1629         448 :   var_properties.Bind(properties);
    1630             : 
    1631         448 :   Label if_smi_hash(this), if_property_array(this), extend_store(this);
    1632         896 :   Branch(TaggedIsSmi(properties), &if_smi_hash, &if_property_array);
    1633             : 
    1634         448 :   BIND(&if_smi_hash);
    1635             :   {
    1636         896 :     Node* hash = SmiToInt32(properties);
    1637             :     Node* encoded_hash =
    1638        1344 :         Word32Shl(hash, Int32Constant(PropertyArray::HashField::kShift));
    1639         448 :     var_encoded_hash.Bind(encoded_hash);
    1640         448 :     var_length.Bind(IntPtrOrSmiConstant(0, mode));
    1641         896 :     var_properties.Bind(EmptyFixedArrayConstant());
    1642         448 :     Goto(&extend_store);
    1643             :   }
    1644             : 
    1645         448 :   BIND(&if_property_array);
    1646             :   {
    1647             :     Node* length_and_hash_int32 = LoadAndUntagToWord32ObjectField(
    1648         896 :         var_properties.value(), PropertyArray::kLengthAndHashOffset);
    1649             :     var_encoded_hash.Bind(Word32And(
    1650        1344 :         length_and_hash_int32, Int32Constant(PropertyArray::HashField::kMask)));
    1651             :     Node* length_intptr = ChangeInt32ToIntPtr(
    1652             :         Word32And(length_and_hash_int32,
    1653        1792 :                   Int32Constant(PropertyArray::LengthField::kMask)));
    1654             :     Node* length = IntPtrToParameter(length_intptr, mode);
    1655         448 :     var_length.Bind(length);
    1656         448 :     Goto(&extend_store);
    1657             :   }
    1658             : 
    1659         448 :   BIND(&extend_store);
    1660             :   {
    1661         448 :     VARIABLE(var_new_properties, MachineRepresentation::kTaggedPointer,
    1662             :              var_properties.value());
    1663         448 :     Label done(this);
    1664             :     // Previous property deletion could have left behind unused backing store
    1665             :     // capacity even for a map that think it doesn't have any unused fields.
    1666             :     // Perform a bounds check to see if we actually have to grow the array.
    1667         896 :     GotoIf(UintPtrLessThan(index, ParameterToIntPtr(var_length.value(), mode)),
    1668         896 :            &done);
    1669             : 
    1670         448 :     Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode);
    1671         448 :     Node* new_capacity = IntPtrOrSmiAdd(var_length.value(), delta, mode);
    1672             : 
    1673             :     // Grow properties array.
    1674             :     DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded <
    1675             :            FixedArrayBase::GetMaxLengthForNewSpaceAllocation(PACKED_ELEMENTS));
    1676             :     // The size of a new properties backing store is guaranteed to be small
    1677             :     // enough that the new backing store will be allocated in new space.
    1678             :     CSA_ASSERT(this,
    1679             :                UintPtrOrSmiLessThan(
    1680             :                    new_capacity,
    1681             :                    IntPtrOrSmiConstant(
    1682             :                        kMaxNumberOfDescriptors + JSObject::kFieldsAdded, mode),
    1683             :                    mode));
    1684             : 
    1685         448 :     Node* new_properties = AllocatePropertyArray(new_capacity, mode);
    1686         448 :     var_new_properties.Bind(new_properties);
    1687             : 
    1688             :     FillPropertyArrayWithUndefined(new_properties, var_length.value(),
    1689         448 :                                    new_capacity, mode);
    1690             : 
    1691             :     // |new_properties| is guaranteed to be in new space, so we can skip
    1692             :     // the write barrier.
    1693             :     CopyPropertyArrayValues(var_properties.value(), new_properties,
    1694             :                             var_length.value(), SKIP_WRITE_BARRIER, mode,
    1695         448 :                             DestroySource::kYes);
    1696             : 
    1697             :     // TODO(gsathya): Clean up the type conversions by creating smarter
    1698             :     // helpers that do the correct op based on the mode.
    1699             :     Node* new_capacity_int32 =
    1700         896 :         TruncateIntPtrToInt32(ParameterToIntPtr(new_capacity, mode));
    1701             :     Node* new_length_and_hash_int32 =
    1702        1344 :         Word32Or(var_encoded_hash.value(), new_capacity_int32);
    1703             :     StoreObjectField(new_properties, PropertyArray::kLengthAndHashOffset,
    1704         896 :                      SmiFromInt32(new_length_and_hash_int32));
    1705         448 :     StoreObjectField(object, JSObject::kPropertiesOrHashOffset, new_properties);
    1706         448 :     Comment("] Extend storage");
    1707         448 :     Goto(&done);
    1708         448 :     BIND(&done);
    1709        1344 :     return var_new_properties.value();
    1710         448 :   }
    1711             : }
    1712             : 
    1713        1344 : void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object,
    1714             :                                         bool is_inobject,
    1715             :                                         Representation representation,
    1716             :                                         Node* value, Label* bailout) {
    1717             :   bool store_value_as_double = representation.IsDouble();
    1718             :   Node* property_storage = object;
    1719        1344 :   if (!is_inobject) {
    1720        1344 :     property_storage = LoadFastProperties(object);
    1721             :   }
    1722             : 
    1723        1344 :   Node* index = DecodeWord<StoreHandler::FieldIndexBits>(handler_word);
    1724        4032 :   Node* offset = IntPtrMul(index, IntPtrConstant(kTaggedSize));
    1725        1344 :   if (representation.IsDouble()) {
    1726         336 :     if (!FLAG_unbox_double_fields || !is_inobject) {
    1727             :       // Load the mutable heap number.
    1728             :       property_storage = LoadObjectField(property_storage, offset);
    1729             :       // Store the double value into it.
    1730         336 :       offset = IntPtrConstant(HeapNumber::kValueOffset);
    1731             :     }
    1732             :   }
    1733             : 
    1734             :   // Do constant value check if necessary.
    1735             :   if (FLAG_track_constant_fields) {
    1736             :     Label done(this);
    1737             :     GotoIfNot(WordEqual(DecodeWord<StoreHandler::KindBits>(handler_word),
    1738             :                         IntPtrConstant(StoreHandler::kConstField)),
    1739             :               &done);
    1740             :     {
    1741             :       if (store_value_as_double) {
    1742             :         Node* current_value =
    1743             :             LoadObjectField(property_storage, offset, MachineType::Float64());
    1744             :         GotoIfNot(Float64Equal(current_value, value), bailout);
    1745             :       } else {
    1746             :         Node* current_value = LoadObjectField(property_storage, offset);
    1747             :         GotoIfNot(WordEqual(current_value, value), bailout);
    1748             :       }
    1749             :       Goto(&done);
    1750             :     }
    1751             :     BIND(&done);
    1752             :   }
    1753             : 
    1754             :   // Do the store.
    1755        1344 :   if (store_value_as_double) {
    1756             :     StoreObjectFieldNoWriteBarrier(property_storage, offset, value,
    1757         336 :                                    MachineRepresentation::kFloat64);
    1758        1008 :   } else if (representation.IsSmi()) {
    1759         336 :     StoreObjectFieldNoWriteBarrier(property_storage, offset, value);
    1760             :   } else {
    1761         672 :     StoreObjectField(property_storage, offset, value);
    1762             :   }
    1763        1344 : }
    1764             : 
    1765         112 : void AccessorAssembler::EmitFastElementsBoundsCheck(Node* object,
    1766             :                                                     Node* elements,
    1767             :                                                     Node* intptr_index,
    1768             :                                                     Node* is_jsarray_condition,
    1769             :                                                     Label* miss) {
    1770         112 :   VARIABLE(var_length, MachineType::PointerRepresentation());
    1771         112 :   Comment("Fast elements bounds check");
    1772         112 :   Label if_array(this), length_loaded(this, &var_length);
    1773         112 :   GotoIf(is_jsarray_condition, &if_array);
    1774             :   {
    1775         336 :     var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements)));
    1776         112 :     Goto(&length_loaded);
    1777             :   }
    1778         112 :   BIND(&if_array);
    1779             :   {
    1780         336 :     var_length.Bind(SmiUntag(LoadFastJSArrayLength(object)));
    1781         112 :     Goto(&length_loaded);
    1782             :   }
    1783         112 :   BIND(&length_loaded);
    1784         448 :   GotoIfNot(UintPtrLessThan(intptr_index, var_length.value()), miss);
    1785         112 : }
    1786             : 
    1787         112 : void AccessorAssembler::EmitElementLoad(
    1788             :     Node* object, Node* elements, Node* elements_kind,
    1789             :     SloppyTNode<IntPtrT> intptr_index, Node* is_jsarray_condition,
    1790             :     Label* if_hole, Label* rebox_double, Variable* var_double_value,
    1791             :     Label* unimplemented_elements_kind, Label* out_of_bounds, Label* miss,
    1792             :     ExitPoint* exit_point) {
    1793         224 :   Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this),
    1794         112 :       if_fast_double(this), if_fast_holey_double(this), if_nonfast(this),
    1795         112 :       if_dictionary(this);
    1796             :   GotoIf(
    1797         224 :       Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
    1798         224 :       &if_nonfast);
    1799             : 
    1800             :   EmitFastElementsBoundsCheck(object, elements, intptr_index,
    1801         112 :                               is_jsarray_condition, out_of_bounds);
    1802             :   int32_t kinds[] = {// Handled by if_fast_packed.
    1803             :                      PACKED_SMI_ELEMENTS, PACKED_ELEMENTS,
    1804             :                      // Handled by if_fast_holey.
    1805             :                      HOLEY_SMI_ELEMENTS, HOLEY_ELEMENTS,
    1806             :                      // Handled by if_fast_double.
    1807             :                      PACKED_DOUBLE_ELEMENTS,
    1808             :                      // Handled by if_fast_holey_double.
    1809         112 :                      HOLEY_DOUBLE_ELEMENTS};
    1810             :   Label* labels[] = {// FAST_{SMI,}_ELEMENTS
    1811             :                      &if_fast_packed, &if_fast_packed,
    1812             :                      // FAST_HOLEY_{SMI,}_ELEMENTS
    1813             :                      &if_fast_holey, &if_fast_holey,
    1814             :                      // PACKED_DOUBLE_ELEMENTS
    1815             :                      &if_fast_double,
    1816             :                      // HOLEY_DOUBLE_ELEMENTS
    1817         112 :                      &if_fast_holey_double};
    1818             :   Switch(elements_kind, unimplemented_elements_kind, kinds, labels,
    1819         112 :          arraysize(kinds));
    1820             : 
    1821         112 :   BIND(&if_fast_packed);
    1822             :   {
    1823         112 :     Comment("fast packed elements");
    1824         112 :     exit_point->Return(LoadFixedArrayElement(CAST(elements), intptr_index));
    1825             :   }
    1826             : 
    1827         112 :   BIND(&if_fast_holey);
    1828             :   {
    1829         112 :     Comment("fast holey elements");
    1830             :     Node* element = LoadFixedArrayElement(CAST(elements), intptr_index);
    1831         224 :     GotoIf(WordEqual(element, TheHoleConstant()), if_hole);
    1832         112 :     exit_point->Return(element);
    1833             :   }
    1834             : 
    1835         112 :   BIND(&if_fast_double);
    1836             :   {
    1837         112 :     Comment("packed double elements");
    1838             :     var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index,
    1839         224 :                                                        MachineType::Float64()));
    1840         112 :     Goto(rebox_double);
    1841             :   }
    1842             : 
    1843         112 :   BIND(&if_fast_holey_double);
    1844             :   {
    1845         112 :     Comment("holey double elements");
    1846             :     Node* value = LoadFixedDoubleArrayElement(elements, intptr_index,
    1847             :                                               MachineType::Float64(), 0,
    1848         224 :                                               INTPTR_PARAMETERS, if_hole);
    1849         112 :     var_double_value->Bind(value);
    1850         112 :     Goto(rebox_double);
    1851             :   }
    1852             : 
    1853         112 :   BIND(&if_nonfast);
    1854             :   {
    1855             :     STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
    1856             :     GotoIf(Int32GreaterThanOrEqual(
    1857             :                elements_kind,
    1858         224 :                Int32Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
    1859         224 :            &if_typed_array);
    1860         224 :     GotoIf(Word32Equal(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)),
    1861         224 :            &if_dictionary);
    1862         112 :     Goto(unimplemented_elements_kind);
    1863             :   }
    1864             : 
    1865         112 :   BIND(&if_dictionary);
    1866             :   {
    1867         112 :     Comment("dictionary elements");
    1868         336 :     GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds);
    1869             : 
    1870             :     TNode<Object> value = BasicLoadNumberDictionaryElement(
    1871         112 :         CAST(elements), intptr_index, miss, if_hole);
    1872         112 :     exit_point->Return(value);
    1873             :   }
    1874             : 
    1875         112 :   BIND(&if_typed_array);
    1876             :   {
    1877         112 :     Comment("typed elements");
    1878             :     // Check if buffer has been detached.
    1879             :     Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
    1880         224 :     GotoIf(IsDetachedBuffer(buffer), miss);
    1881             : 
    1882             :     // Bounds check.
    1883         336 :     Node* length = SmiUntag(LoadJSTypedArrayLength(CAST(object)));
    1884         224 :     GotoIfNot(UintPtrLessThan(intptr_index, length), out_of_bounds);
    1885             : 
    1886         224 :     Node* backing_store = LoadFixedTypedArrayBackingStore(CAST(elements));
    1887             : 
    1888         112 :     Label uint8_elements(this), int8_elements(this), uint16_elements(this),
    1889         112 :         int16_elements(this), uint32_elements(this), int32_elements(this),
    1890         112 :         float32_elements(this), float64_elements(this), bigint64_elements(this),
    1891         112 :         biguint64_elements(this);
    1892             :     Label* elements_kind_labels[] = {
    1893             :         &uint8_elements,    &uint8_elements,    &int8_elements,
    1894             :         &uint16_elements,   &int16_elements,    &uint32_elements,
    1895             :         &int32_elements,    &float32_elements,  &float64_elements,
    1896         112 :         &bigint64_elements, &biguint64_elements};
    1897             :     int32_t elements_kinds[] = {
    1898             :         UINT8_ELEMENTS,    UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
    1899             :         UINT16_ELEMENTS,   INT16_ELEMENTS,         UINT32_ELEMENTS,
    1900             :         INT32_ELEMENTS,    FLOAT32_ELEMENTS,       FLOAT64_ELEMENTS,
    1901         112 :         BIGINT64_ELEMENTS, BIGUINT64_ELEMENTS};
    1902             :     const size_t kTypedElementsKindCount =
    1903             :         LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
    1904             :         FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1;
    1905             :     DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
    1906             :     DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
    1907             :     Switch(elements_kind, miss, elements_kinds, elements_kind_labels,
    1908         112 :            kTypedElementsKindCount);
    1909         112 :     BIND(&uint8_elements);
    1910             :     {
    1911         112 :       Comment("UINT8_ELEMENTS");  // Handles UINT8_CLAMPED_ELEMENTS too.
    1912         112 :       Node* element = Load(MachineType::Uint8(), backing_store, intptr_index);
    1913         224 :       exit_point->Return(SmiFromInt32(element));
    1914             :     }
    1915         112 :     BIND(&int8_elements);
    1916             :     {
    1917         112 :       Comment("INT8_ELEMENTS");
    1918         112 :       Node* element = Load(MachineType::Int8(), backing_store, intptr_index);
    1919         224 :       exit_point->Return(SmiFromInt32(element));
    1920             :     }
    1921         112 :     BIND(&uint16_elements);
    1922             :     {
    1923         112 :       Comment("UINT16_ELEMENTS");
    1924         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(1));
    1925         112 :       Node* element = Load(MachineType::Uint16(), backing_store, index);
    1926         224 :       exit_point->Return(SmiFromInt32(element));
    1927             :     }
    1928         112 :     BIND(&int16_elements);
    1929             :     {
    1930         112 :       Comment("INT16_ELEMENTS");
    1931         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(1));
    1932         112 :       Node* element = Load(MachineType::Int16(), backing_store, index);
    1933         224 :       exit_point->Return(SmiFromInt32(element));
    1934             :     }
    1935         112 :     BIND(&uint32_elements);
    1936             :     {
    1937         112 :       Comment("UINT32_ELEMENTS");
    1938         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1939         112 :       Node* element = Load(MachineType::Uint32(), backing_store, index);
    1940         224 :       exit_point->Return(ChangeUint32ToTagged(element));
    1941             :     }
    1942         112 :     BIND(&int32_elements);
    1943             :     {
    1944         112 :       Comment("INT32_ELEMENTS");
    1945         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1946         112 :       Node* element = Load(MachineType::Int32(), backing_store, index);
    1947         224 :       exit_point->Return(ChangeInt32ToTagged(element));
    1948             :     }
    1949         112 :     BIND(&float32_elements);
    1950             :     {
    1951         112 :       Comment("FLOAT32_ELEMENTS");
    1952         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(2));
    1953         112 :       Node* element = Load(MachineType::Float32(), backing_store, index);
    1954         224 :       var_double_value->Bind(ChangeFloat32ToFloat64(element));
    1955         112 :       Goto(rebox_double);
    1956             :     }
    1957         112 :     BIND(&float64_elements);
    1958             :     {
    1959         112 :       Comment("FLOAT64_ELEMENTS");
    1960         336 :       Node* index = WordShl(intptr_index, IntPtrConstant(3));
    1961         112 :       Node* element = Load(MachineType::Float64(), backing_store, index);
    1962         112 :       var_double_value->Bind(element);
    1963         112 :       Goto(rebox_double);
    1964             :     }
    1965         112 :     BIND(&bigint64_elements);
    1966             :     {
    1967         112 :       Comment("BIGINT64_ELEMENTS");
    1968             :       exit_point->Return(LoadFixedTypedArrayElementAsTagged(
    1969         112 :           backing_store, intptr_index, BIGINT64_ELEMENTS, INTPTR_PARAMETERS));
    1970             :     }
    1971         112 :     BIND(&biguint64_elements);
    1972             :     {
    1973         112 :       Comment("BIGUINT64_ELEMENTS");
    1974             :       exit_point->Return(LoadFixedTypedArrayElementAsTagged(
    1975         112 :           backing_store, intptr_index, BIGUINT64_ELEMENTS, INTPTR_PARAMETERS));
    1976         112 :     }
    1977         112 :   }
    1978         112 : }
    1979             : 
    1980           0 : void AccessorAssembler::NameDictionaryNegativeLookup(Node* object,
    1981             :                                                      SloppyTNode<Name> name,
    1982             :                                                      Label* miss) {
    1983             :   CSA_ASSERT(this, IsDictionaryMap(LoadMap(object)));
    1984           0 :   TNode<NameDictionary> properties = CAST(LoadSlowProperties(object));
    1985             :   // Ensure the property does not exist in a dictionary-mode object.
    1986           0 :   TVARIABLE(IntPtrT, var_name_index);
    1987           0 :   Label done(this);
    1988             :   NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index,
    1989           0 :                                        &done);
    1990           0 :   BIND(&done);
    1991           0 : }
    1992             : 
    1993         952 : void AccessorAssembler::BranchIfStrictMode(Node* vector, Node* slot,
    1994             :                                            Label* if_strict) {
    1995             :   Node* sfi =
    1996         952 :       LoadObjectField(vector, FeedbackVector::kSharedFunctionInfoOffset);
    1997             :   TNode<FeedbackMetadata> metadata = CAST(LoadObjectField(
    1998             :       sfi, SharedFunctionInfo::kOuterScopeInfoOrFeedbackMetadataOffset));
    1999        1904 :   Node* slot_int = SmiToInt32(slot);
    2000             : 
    2001             :   // See VectorICComputer::index().
    2002             :   const int kItemsPerWord = FeedbackMetadata::VectorICComputer::kItemsPerWord;
    2003        2856 :   Node* word_index = Int32Div(slot_int, Int32Constant(kItemsPerWord));
    2004        2856 :   Node* word_offset = Int32Mod(slot_int, Int32Constant(kItemsPerWord));
    2005             : 
    2006             :   int32_t first_item = FeedbackMetadata::kHeaderSize - kHeapObjectTag;
    2007             :   Node* offset =
    2008         952 :       ElementOffsetFromIndex(ChangeInt32ToIntPtr(word_index), UINT32_ELEMENTS,
    2009        2856 :                              INTPTR_PARAMETERS, first_item);
    2010             : 
    2011         952 :   Node* data = Load(MachineType::Int32(), metadata, offset);
    2012             : 
    2013             :   // See VectorICComputer::decode().
    2014             :   const int kBitsPerItem = FeedbackMetadata::kFeedbackSlotKindBits;
    2015        2856 :   Node* shift = Int32Mul(word_offset, Int32Constant(kBitsPerItem));
    2016             :   const int kMask = FeedbackMetadata::VectorICComputer::kMask;
    2017        3808 :   Node* kind = Word32And(Word32Shr(data, shift), Int32Constant(kMask));
    2018             : 
    2019             :   STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
    2020             :                 FeedbackSlotKind::kLastSloppyKind);
    2021             :   STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
    2022             :                 FeedbackSlotKind::kLastSloppyKind);
    2023             :   STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
    2024             :                 FeedbackSlotKind::kLastSloppyKind);
    2025             :   GotoIfNot(Int32LessThanOrEqual(kind, Int32Constant(static_cast<int>(
    2026        1904 :                                            FeedbackSlotKind::kLastSloppyKind))),
    2027        1904 :             if_strict);
    2028         952 : }
    2029             : 
    2030         504 : void AccessorAssembler::InvalidateValidityCellIfPrototype(Node* map,
    2031             :                                                           Node* bitfield2) {
    2032        1008 :   Label is_prototype(this), cont(this);
    2033         504 :   if (bitfield2 == nullptr) {
    2034         448 :     bitfield2 = LoadMapBitField2(map);
    2035             :   }
    2036             : 
    2037        1008 :   Branch(IsSetWord32(bitfield2, Map::IsPrototypeMapBit::kMask), &is_prototype,
    2038        1008 :          &cont);
    2039             : 
    2040         504 :   BIND(&is_prototype);
    2041             :   {
    2042             :     Node* maybe_prototype_info =
    2043             :         LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
    2044             :     // If there's no prototype info then there's nothing to invalidate.
    2045        1008 :     GotoIf(TaggedIsSmi(maybe_prototype_info), &cont);
    2046             : 
    2047             :     Node* function = ExternalConstant(
    2048        1008 :         ExternalReference::invalidate_prototype_chains_function());
    2049             :     CallCFunction1(MachineType::AnyTagged(), MachineType::AnyTagged(), function,
    2050         504 :                    map);
    2051         504 :     Goto(&cont);
    2052             :   }
    2053        1008 :   BIND(&cont);
    2054         504 : }
    2055             : 
    2056          56 : void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map,
    2057             :                                            SloppyTNode<Int32T> instance_type,
    2058             :                                            Node* index, Label* slow) {
    2059          56 :   Comment("integer index");
    2060             : 
    2061          56 :   ExitPoint direct_exit(this);
    2062             : 
    2063          56 :   Label if_custom(this), if_element_hole(this), if_oob(this);
    2064             :   // Receivers requiring non-standard element accesses (interceptors, access
    2065             :   // checks, strings and string wrappers, proxies) are handled in the runtime.
    2066         112 :   GotoIf(IsCustomElementsReceiverInstanceType(instance_type), &if_custom);
    2067             :   Node* elements = LoadElements(receiver);
    2068         112 :   Node* elements_kind = LoadMapElementsKind(receiver_map);
    2069         112 :   Node* is_jsarray_condition = InstanceTypeEqual(instance_type, JS_ARRAY_TYPE);
    2070         112 :   VARIABLE(var_double_value, MachineRepresentation::kFloat64);
    2071          56 :   Label rebox_double(this, &var_double_value);
    2072             : 
    2073             :   // Unimplemented elements kinds fall back to a runtime call.
    2074             :   Label* unimplemented_elements_kind = slow;
    2075         112 :   IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
    2076             :   EmitElementLoad(receiver, elements, elements_kind, index,
    2077             :                   is_jsarray_condition, &if_element_hole, &rebox_double,
    2078             :                   &var_double_value, unimplemented_elements_kind, &if_oob, slow,
    2079          56 :                   &direct_exit);
    2080             : 
    2081          56 :   BIND(&rebox_double);
    2082         168 :   Return(AllocateHeapNumberWithValue(var_double_value.value()));
    2083             : 
    2084          56 :   BIND(&if_oob);
    2085             :   {
    2086          56 :     Comment("out of bounds");
    2087             :     // Positive OOB indices are effectively the same as hole loads.
    2088         112 :     GotoIf(IntPtrGreaterThanOrEqual(index, IntPtrConstant(0)),
    2089         112 :            &if_element_hole);
    2090             :     // Negative keys can't take the fast OOB path, except for typed arrays.
    2091         112 :     GotoIfNot(InstanceTypeEqual(instance_type, JS_TYPED_ARRAY_TYPE), slow);
    2092         112 :     Return(UndefinedConstant());
    2093             :   }
    2094             : 
    2095          56 :   BIND(&if_element_hole);
    2096             :   {
    2097          56 :     Comment("found the hole");
    2098             :     Label return_undefined(this);
    2099          56 :     BranchIfPrototypesHaveNoElements(receiver_map, &return_undefined, slow);
    2100             : 
    2101          56 :     BIND(&return_undefined);
    2102         112 :     Return(UndefinedConstant());
    2103             :   }
    2104             : 
    2105          56 :   BIND(&if_custom);
    2106             :   {
    2107          56 :     Comment("check if string");
    2108         112 :     GotoIfNot(IsStringInstanceType(instance_type), slow);
    2109          56 :     Comment("load string character");
    2110          56 :     TNode<IntPtrT> length = LoadStringLengthAsWord(receiver);
    2111         112 :     GotoIfNot(UintPtrLessThan(index, length), slow);
    2112         112 :     IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1);
    2113             :     TailCallBuiltin(Builtins::kStringCharAt, NoContextConstant(), receiver,
    2114         112 :                     index);
    2115             :   }
    2116          56 : }
    2117             : 
    2118         168 : void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map,
    2119             :                                             SloppyTNode<Int32T> instance_type,
    2120             :                                             const LoadICParameters* p,
    2121             :                                             Label* slow,
    2122             :                                             UseStubCache use_stub_cache) {
    2123         168 :   ExitPoint direct_exit(this);
    2124             : 
    2125         168 :   Comment("key is unique name");
    2126         168 :   Label if_found_on_receiver(this), if_property_dictionary(this),
    2127         168 :       lookup_prototype_chain(this), special_receiver(this);
    2128         336 :   VARIABLE(var_details, MachineRepresentation::kWord32);
    2129         336 :   VARIABLE(var_value, MachineRepresentation::kTagged);
    2130             : 
    2131             :   // Receivers requiring non-standard accesses (interceptors, access
    2132             :   // checks, strings and string wrappers) are handled in the runtime.
    2133         336 :   GotoIf(IsSpecialReceiverInstanceType(instance_type), &special_receiver);
    2134             : 
    2135             :   // Check if the receiver has fast or slow properties.
    2136         336 :   Node* bitfield3 = LoadMapBitField3(receiver_map);
    2137             :   GotoIf(IsSetWord32<Map::IsDictionaryMapBit>(bitfield3),
    2138         168 :          &if_property_dictionary);
    2139             : 
    2140             :   // Try looking up the property on the receiver; if unsuccessful, look
    2141             :   // for a handler in the stub cache.
    2142         168 :   TNode<DescriptorArray> descriptors = LoadMapDescriptors(receiver_map);
    2143             : 
    2144         168 :   Label if_descriptor_found(this), stub_cache(this);
    2145             :   TVARIABLE(IntPtrT, var_name_index);
    2146             :   Label* notfound =
    2147         168 :       use_stub_cache == kUseStubCache ? &stub_cache : &lookup_prototype_chain;
    2148             :   DescriptorLookup(p->name, descriptors, bitfield3, &if_descriptor_found,
    2149         336 :                    &var_name_index, notfound);
    2150             : 
    2151         168 :   BIND(&if_descriptor_found);
    2152             :   {
    2153             :     LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
    2154             :                                var_name_index.value(), &var_details,
    2155         168 :                                &var_value);
    2156         168 :     Goto(&if_found_on_receiver);
    2157             :   }
    2158             : 
    2159         168 :   if (use_stub_cache == kUseStubCache) {
    2160          56 :     BIND(&stub_cache);
    2161          56 :     Comment("stub cache probe for fast property load");
    2162             :     TVARIABLE(MaybeObject, var_handler);
    2163          56 :     Label found_handler(this, &var_handler), stub_cache_miss(this);
    2164             :     TryProbeStubCache(isolate()->load_stub_cache(), receiver, p->name,
    2165          56 :                       &found_handler, &var_handler, &stub_cache_miss);
    2166          56 :     BIND(&found_handler);
    2167             :     {
    2168             :       HandleLoadICHandlerCase(p, CAST(var_handler.value()), &stub_cache_miss,
    2169          56 :                               &direct_exit);
    2170             :     }
    2171             : 
    2172          56 :     BIND(&stub_cache_miss);
    2173             :     {
    2174             :       // TODO(jkummerow): Check if the property exists on the prototype
    2175             :       // chain. If it doesn't, then there's no point in missing.
    2176          56 :       Comment("KeyedLoadGeneric_miss");
    2177             :       TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
    2178         112 :                       p->name, p->slot, p->vector);
    2179             :     }
    2180             :   }
    2181             : 
    2182         168 :   BIND(&if_property_dictionary);
    2183             :   {
    2184         168 :     Comment("dictionary property load");
    2185             :     // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
    2186             :     // seeing global objects here (which would need special handling).
    2187             : 
    2188             :     TVARIABLE(IntPtrT, var_name_index);
    2189         168 :     Label dictionary_found(this, &var_name_index);
    2190         168 :     TNode<NameDictionary> properties = CAST(LoadSlowProperties(receiver));
    2191         168 :     NameDictionaryLookup<NameDictionary>(properties, CAST(p->name),
    2192             :                                          &dictionary_found, &var_name_index,
    2193         168 :                                          &lookup_prototype_chain);
    2194         168 :     BIND(&dictionary_found);
    2195             :     {
    2196             :       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
    2197         168 :                                      &var_details, &var_value);
    2198         168 :       Goto(&if_found_on_receiver);
    2199             :     }
    2200             :   }
    2201             : 
    2202         168 :   BIND(&if_found_on_receiver);
    2203             :   {
    2204             :     Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
    2205         336 :                                        p->context, receiver, slow);
    2206         336 :     IncrementCounter(isolate()->counters()->ic_keyed_load_generic_symbol(), 1);
    2207         168 :     Return(value);
    2208             :   }
    2209             : 
    2210         168 :   BIND(&lookup_prototype_chain);
    2211             :   {
    2212         168 :     VARIABLE(var_holder_map, MachineRepresentation::kTagged);
    2213         336 :     VARIABLE(var_holder_instance_type, MachineRepresentation::kWord32);
    2214         168 :     Label return_undefined(this);
    2215         168 :     Variable* merged_variables[] = {&var_holder_map, &var_holder_instance_type};
    2216         336 :     Label loop(this, arraysize(merged_variables), merged_variables);
    2217             : 
    2218         168 :     var_holder_map.Bind(receiver_map);
    2219         168 :     var_holder_instance_type.Bind(instance_type);
    2220             :     // Private symbols must not be looked up on the prototype chain.
    2221         504 :     GotoIf(IsPrivateSymbol(p->name), &return_undefined);
    2222         168 :     Goto(&loop);
    2223         168 :     BIND(&loop);
    2224             :     {
    2225             :       // Bailout if it can be an integer indexed exotic case.
    2226             :       GotoIf(InstanceTypeEqual(var_holder_instance_type.value(),
    2227         336 :                                JS_TYPED_ARRAY_TYPE),
    2228         336 :              slow);
    2229         504 :       Node* proto = LoadMapPrototype(var_holder_map.value());
    2230         336 :       GotoIf(WordEqual(proto, NullConstant()), &return_undefined);
    2231         336 :       Node* proto_map = LoadMap(proto);
    2232         336 :       Node* proto_instance_type = LoadMapInstanceType(proto_map);
    2233         168 :       var_holder_map.Bind(proto_map);
    2234         168 :       var_holder_instance_type.Bind(proto_instance_type);
    2235         168 :       Label next_proto(this), return_value(this, &var_value), goto_slow(this);
    2236             :       TryGetOwnProperty(p->context, receiver, proto, proto_map,
    2237             :                         proto_instance_type, p->name, &return_value, &var_value,
    2238         168 :                         &next_proto, &goto_slow);
    2239             : 
    2240             :       // This trampoline and the next are required to appease Turbofan's
    2241             :       // variable merging.
    2242         168 :       BIND(&next_proto);
    2243         168 :       Goto(&loop);
    2244             : 
    2245         168 :       BIND(&goto_slow);
    2246         168 :       Goto(slow);
    2247             : 
    2248         168 :       BIND(&return_value);
    2249         504 :       Return(var_value.value());
    2250             :     }
    2251             : 
    2252         168 :     BIND(&return_undefined);
    2253         504 :     Return(UndefinedConstant());
    2254             :   }
    2255             : 
    2256         168 :   BIND(&special_receiver);
    2257             :   {
    2258             :     // TODO(jkummerow): Consider supporting JSModuleNamespace.
    2259         336 :     GotoIfNot(InstanceTypeEqual(instance_type, JS_PROXY_TYPE), slow);
    2260             : 
    2261             :     // Private field/symbol lookup is not supported.
    2262         504 :     GotoIf(IsPrivateSymbol(p->name), slow);
    2263             : 
    2264             :     direct_exit.ReturnCallStub(
    2265             :         Builtins::CallableFor(isolate(), Builtins::kProxyGetProperty),
    2266             :         p->context, receiver /*holder is the same as receiver*/, p->name,
    2267         336 :         receiver, SmiConstant(OnNonExistent::kReturnUndefined));
    2268             :   }
    2269         168 : }
    2270             : 
    2271             : //////////////////// Stub cache access helpers.
    2272             : 
    2273             : enum AccessorAssembler::StubCacheTable : int {
    2274             :   kPrimary = static_cast<int>(StubCache::kPrimary),
    2275             :   kSecondary = static_cast<int>(StubCache::kSecondary)
    2276             : };
    2277             : 
    2278         295 : Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) {
    2279             :   // See v8::internal::StubCache::PrimaryOffset().
    2280             :   STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift);
    2281             :   // Compute the hash of the name (use entire hash field).
    2282         590 :   Node* hash_field = LoadNameHashField(name);
    2283             :   CSA_ASSERT(this,
    2284             :              Word32Equal(Word32And(hash_field,
    2285             :                                    Int32Constant(Name::kHashNotComputedMask)),
    2286             :                          Int32Constant(0)));
    2287             : 
    2288             :   // Using only the low bits in 64-bit mode is unlikely to increase the
    2289             :   // risk of collision even if the heap is spread over an area larger than
    2290             :   // 4Gb (and not at all if it isn't).
    2291         885 :   Node* map32 = TruncateIntPtrToInt32(BitcastTaggedToWord(map));
    2292             :   // Base the offset on a simple combination of name and map.
    2293         590 :   Node* hash = Int32Add(hash_field, map32);
    2294             :   uint32_t mask = (StubCache::kPrimaryTableSize - 1)
    2295             :                   << StubCache::kCacheIndexShift;
    2296        1180 :   return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
    2297             : }
    2298             : 
    2299         290 : Node* AccessorAssembler::StubCacheSecondaryOffset(Node* name, Node* seed) {
    2300             :   // See v8::internal::StubCache::SecondaryOffset().
    2301             : 
    2302             :   // Use the seed from the primary cache in the secondary cache.
    2303         870 :   Node* name32 = TruncateIntPtrToInt32(BitcastTaggedToWord(name));
    2304         870 :   Node* hash = Int32Sub(TruncateIntPtrToInt32(seed), name32);
    2305         870 :   hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic));
    2306             :   int32_t mask = (StubCache::kSecondaryTableSize - 1)
    2307             :                  << StubCache::kCacheIndexShift;
    2308        1160 :   return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask)));
    2309             : }
    2310             : 
    2311         570 : void AccessorAssembler::TryProbeStubCacheTable(
    2312             :     StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset,
    2313             :     Node* name, Node* map, Label* if_handler,
    2314             :     TVariable<MaybeObject>* var_handler, Label* if_miss) {
    2315         570 :   StubCache::Table table = static_cast<StubCache::Table>(table_id);
    2316             :   // The {table_offset} holds the entry offset times four (due to masking
    2317             :   // and shifting optimizations).
    2318             :   const int kMultiplier = sizeof(StubCache::Entry) >> Name::kHashShift;
    2319        1710 :   entry_offset = IntPtrMul(entry_offset, IntPtrConstant(kMultiplier));
    2320             : 
    2321             :   // Check that the key in the entry matches the name.
    2322             :   Node* key_base = ExternalConstant(
    2323        1140 :       ExternalReference::Create(stub_cache->key_reference(table)));
    2324         570 :   Node* entry_key = Load(MachineType::Pointer(), key_base, entry_offset);
    2325        1140 :   GotoIf(WordNotEqual(name, entry_key), if_miss);
    2326             : 
    2327             :   // Get the map entry from the cache.
    2328             :   DCHECK_EQ(kSystemPointerSize * 2,
    2329             :             stub_cache->map_reference(table).address() -
    2330             :                 stub_cache->key_reference(table).address());
    2331             :   Node* entry_map =
    2332             :       Load(MachineType::Pointer(), key_base,
    2333        1710 :            IntPtrAdd(entry_offset, IntPtrConstant(kSystemPointerSize * 2)));
    2334        1140 :   GotoIf(WordNotEqual(map, entry_map), if_miss);
    2335             : 
    2336             :   DCHECK_EQ(kSystemPointerSize, stub_cache->value_reference(table).address() -
    2337             :                                     stub_cache->key_reference(table).address());
    2338             :   TNode<MaybeObject> handler = ReinterpretCast<MaybeObject>(
    2339             :       Load(MachineType::AnyTagged(), key_base,
    2340        1710 :            IntPtrAdd(entry_offset, IntPtrConstant(kSystemPointerSize))));
    2341             : 
    2342             :   // We found the handler.
    2343             :   *var_handler = handler;
    2344         570 :   Goto(if_handler);
    2345         570 : }
    2346             : 
    2347         285 : void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver,
    2348             :                                           Node* name, Label* if_handler,
    2349             :                                           TVariable<MaybeObject>* var_handler,
    2350             :                                           Label* if_miss) {
    2351         570 :   Label try_secondary(this), miss(this);
    2352             : 
    2353         285 :   Counters* counters = isolate()->counters();
    2354         285 :   IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
    2355             : 
    2356             :   // Check that the {receiver} isn't a smi.
    2357         570 :   GotoIf(TaggedIsSmi(receiver), &miss);
    2358             : 
    2359         570 :   Node* receiver_map = LoadMap(receiver);
    2360             : 
    2361             :   // Probe the primary table.
    2362         285 :   Node* primary_offset = StubCachePrimaryOffset(name, receiver_map);
    2363             :   TryProbeStubCacheTable(stub_cache, kPrimary, primary_offset, name,
    2364         285 :                          receiver_map, if_handler, var_handler, &try_secondary);
    2365             : 
    2366         285 :   BIND(&try_secondary);
    2367             :   {
    2368             :     // Probe the secondary table.
    2369         285 :     Node* secondary_offset = StubCacheSecondaryOffset(name, primary_offset);
    2370             :     TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
    2371         285 :                            receiver_map, if_handler, var_handler, &miss);
    2372             :   }
    2373             : 
    2374         285 :   BIND(&miss);
    2375             :   {
    2376         285 :     IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
    2377         285 :     Goto(if_miss);
    2378         285 :   }
    2379         285 : }
    2380             : 
    2381             : //////////////////// Entry points into private implementation (one per stub).
    2382             : 
    2383         168 : void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p,
    2384             :                                                ExitPoint* exit_point) {
    2385             :   // Must be kept in sync with LoadIC.
    2386             : 
    2387             :   // This function is hand-tuned to omit frame construction for common cases,
    2388             :   // e.g.: monomorphic field and constant loads through smi handlers.
    2389             :   // Polymorphic ICs with a hit in the first two entries also omit frames.
    2390             :   // TODO(jgruber): Frame omission is fragile and can be affected by minor
    2391             :   // changes in control flow and logic. We currently have no way of ensuring
    2392             :   // that no frame is constructed, so it's easy to break this optimization by
    2393             :   // accident.
    2394         336 :   Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred);
    2395             : 
    2396         504 :   GotoIf(IsUndefined(p->vector), &miss);
    2397             : 
    2398             :   // Inlined fast path.
    2399             :   {
    2400         168 :     Comment("LoadIC_BytecodeHandler_fast");
    2401             : 
    2402         504 :     Node* recv_map = LoadReceiverMap(p->receiver);
    2403         336 :     GotoIf(IsDeprecatedMap(recv_map), &miss);
    2404             : 
    2405             :     TVARIABLE(MaybeObject, var_handler);
    2406         168 :     Label try_polymorphic(this), if_handler(this, &var_handler);
    2407             : 
    2408             :     TNode<MaybeObject> feedback =
    2409             :         TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler,
    2410         168 :                            &var_handler, &try_polymorphic);
    2411             : 
    2412         168 :     BIND(&if_handler);
    2413         168 :     HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, exit_point);
    2414             : 
    2415         168 :     BIND(&try_polymorphic);
    2416             :     {
    2417             :       TNode<HeapObject> strong_feedback =
    2418         168 :           GetHeapObjectIfStrong(feedback, &miss);
    2419         504 :       GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &stub_call);
    2420             :       HandlePolymorphicCase(recv_map, CAST(strong_feedback), &if_handler,
    2421         168 :                             &var_handler, &miss, 2);
    2422             :     }
    2423             :   }
    2424             : 
    2425         168 :   BIND(&stub_call);
    2426             :   {
    2427         168 :     Comment("LoadIC_BytecodeHandler_noninlined");
    2428             : 
    2429             :     // Call into the stub that implements the non-inlined parts of LoadIC.
    2430             :     Callable ic =
    2431         168 :         Builtins::CallableFor(isolate(), Builtins::kLoadIC_Noninlined);
    2432             :     Node* code_target = HeapConstant(ic.code());
    2433             :     exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context,
    2434         504 :                                p->receiver, p->name, p->slot, p->vector);
    2435             :   }
    2436             : 
    2437         168 :   BIND(&miss);
    2438             :   {
    2439         168 :     Comment("LoadIC_BytecodeHandler_miss");
    2440             : 
    2441             :     exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context,
    2442         168 :                                   p->receiver, p->name, p->slot, p->vector);
    2443         168 :   }
    2444         168 : }
    2445             : 
    2446          56 : void AccessorAssembler::LoadIC(const LoadICParameters* p) {
    2447             :   // Must be kept in sync with LoadIC_BytecodeHandler.
    2448             : 
    2449          56 :   ExitPoint direct_exit(this);
    2450             : 
    2451          56 :   TVARIABLE(MaybeObject, var_handler);
    2452          56 :   Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred),
    2453          56 :       try_polymorphic(this), miss(this, Label::kDeferred);
    2454             : 
    2455         168 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2456         112 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2457             : 
    2458             :   // Check monomorphic case.
    2459             :   TNode<MaybeObject> feedback =
    2460             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2461          56 :                          &var_handler, &try_polymorphic);
    2462          56 :   BIND(&if_handler);
    2463          56 :   HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit);
    2464             : 
    2465          56 :   BIND(&try_polymorphic);
    2466          56 :   TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    2467             :   {
    2468             :     // Check polymorphic case.
    2469          56 :     Comment("LoadIC_try_polymorphic");
    2470         168 :     GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &non_inlined);
    2471             :     HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
    2472          56 :                           &var_handler, &miss, 2);
    2473             :   }
    2474             : 
    2475          56 :   BIND(&non_inlined);
    2476             :   {
    2477             :     LoadIC_Noninlined(p, receiver_map, strong_feedback, &var_handler,
    2478          56 :                       &if_handler, &miss, &direct_exit);
    2479             :   }
    2480             : 
    2481          56 :   BIND(&miss);
    2482             :   direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver,
    2483          56 :                                 p->name, p->slot, p->vector);
    2484          56 : }
    2485             : 
    2486         112 : void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p,
    2487             :                                           Node* receiver_map,
    2488             :                                           TNode<HeapObject> feedback,
    2489             :                                           TVariable<MaybeObject>* var_handler,
    2490             :                                           Label* if_handler, Label* miss,
    2491             :                                           ExitPoint* exit_point) {
    2492         112 :   Label try_uninitialized(this, Label::kDeferred);
    2493             : 
    2494             :   // Neither deprecated map nor monomorphic. These cases are handled in the
    2495             :   // bytecode handler.
    2496             :   CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
    2497             :   CSA_ASSERT(this, WordNotEqual(receiver_map, feedback));
    2498             :   CSA_ASSERT(this, Word32BinaryNot(IsWeakFixedArrayMap(LoadMap(feedback))));
    2499             :   DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep());
    2500             : 
    2501             :   {
    2502             :     // Check megamorphic case.
    2503         112 :     GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    2504         112 :               &try_uninitialized);
    2505             : 
    2506             :     TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name,
    2507         112 :                       if_handler, var_handler, miss);
    2508             :   }
    2509             : 
    2510         112 :   BIND(&try_uninitialized);
    2511             :   {
    2512             :     // Check uninitialized case.
    2513         112 :     GotoIfNot(WordEqual(feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
    2514         112 :               miss);
    2515             :     exit_point->ReturnCallStub(
    2516             :         Builtins::CallableFor(isolate(), Builtins::kLoadIC_Uninitialized),
    2517         224 :         p->context, p->receiver, p->name, p->slot, p->vector);
    2518         112 :   }
    2519         112 : }
    2520             : 
    2521          56 : void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
    2522          56 :   Label miss(this, Label::kDeferred);
    2523          56 :   Node* receiver = p->receiver;
    2524         112 :   GotoIf(TaggedIsSmi(receiver), &miss);
    2525         112 :   Node* receiver_map = LoadMap(receiver);
    2526         112 :   Node* instance_type = LoadMapInstanceType(receiver_map);
    2527             : 
    2528             :   // Optimistically write the state transition to the vector.
    2529             :   StoreFeedbackVectorSlot(p->vector, p->slot,
    2530             :                           LoadRoot(RootIndex::kpremonomorphic_symbol),
    2531         112 :                           SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
    2532             :   StoreWeakReferenceInFeedbackVector(p->vector, p->slot, receiver_map,
    2533         112 :                                      kTaggedSize, SMI_PARAMETERS);
    2534             : 
    2535             :   {
    2536             :     // Special case for Function.prototype load, because it's very common
    2537             :     // for ICs that are only executed once (MyFunc.prototype.foo = ...).
    2538             :     Label not_function_prototype(this, Label::kDeferred);
    2539          56 :     GotoIfNot(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE),
    2540         112 :               &not_function_prototype);
    2541         168 :     GotoIfNot(IsPrototypeString(p->name), &not_function_prototype);
    2542             : 
    2543             :     GotoIfPrototypeRequiresRuntimeLookup(CAST(receiver), CAST(receiver_map),
    2544          56 :                                          &not_function_prototype);
    2545         112 :     Return(LoadJSFunctionPrototype(receiver, &miss));
    2546          56 :     BIND(&not_function_prototype);
    2547             :   }
    2548             : 
    2549             :   GenericPropertyLoad(receiver, receiver_map, instance_type, p, &miss,
    2550          56 :                       kDontUseStubCache);
    2551             : 
    2552          56 :   BIND(&miss);
    2553             :   {
    2554             :     // Undo the optimistic state transition.
    2555             :     StoreFeedbackVectorSlot(p->vector, p->slot,
    2556             :                             LoadRoot(RootIndex::kuninitialized_symbol),
    2557         112 :                             SKIP_WRITE_BARRIER, 0, SMI_PARAMETERS);
    2558             : 
    2559             :     TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name,
    2560         112 :                     p->slot, p->vector);
    2561          56 :   }
    2562          56 : }
    2563             : 
    2564         784 : void AccessorAssembler::LoadGlobalIC(TNode<FeedbackVector> vector, Node* slot,
    2565             :                                      const LazyNode<Context>& lazy_context,
    2566             :                                      const LazyNode<Name>& lazy_name,
    2567             :                                      TypeofMode typeof_mode,
    2568             :                                      ExitPoint* exit_point,
    2569             :                                      ParameterMode slot_mode) {
    2570        1568 :   Label try_handler(this, Label::kDeferred), miss(this, Label::kDeferred);
    2571             :   LoadGlobalIC_TryPropertyCellCase(vector, slot, lazy_context, exit_point,
    2572         784 :                                    &try_handler, &miss, slot_mode);
    2573             : 
    2574         784 :   BIND(&try_handler);
    2575             :   LoadGlobalIC_TryHandlerCase(vector, slot, lazy_context, lazy_name,
    2576         784 :                               typeof_mode, exit_point, &miss, slot_mode);
    2577             : 
    2578         784 :   BIND(&miss);
    2579             :   {
    2580         784 :     Comment("LoadGlobalIC_MissCase");
    2581         784 :     TNode<Context> context = lazy_context();
    2582         784 :     TNode<Name> name = lazy_name();
    2583             :     exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name,
    2584             :                                   ParameterToTagged(slot, slot_mode), vector,
    2585         784 :                                   SmiConstant(typeof_mode));
    2586         784 :   }
    2587         784 : }
    2588             : 
    2589         784 : void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
    2590             :     TNode<FeedbackVector> vector, Node* slot,
    2591             :     const LazyNode<Context>& lazy_context, ExitPoint* exit_point,
    2592             :     Label* try_handler, Label* miss, ParameterMode slot_mode) {
    2593         784 :   Comment("LoadGlobalIC_TryPropertyCellCase");
    2594             : 
    2595         784 :   Label if_lexical_var(this), if_property_cell(this);
    2596             :   TNode<MaybeObject> maybe_weak_ref =
    2597         784 :       LoadFeedbackVectorSlot(vector, slot, 0, slot_mode);
    2598        1568 :   Branch(TaggedIsSmi(maybe_weak_ref), &if_lexical_var, &if_property_cell);
    2599             : 
    2600         784 :   BIND(&if_property_cell);
    2601             :   {
    2602             :     // Load value or try handler case if the weak reference is cleared.
    2603             :     CSA_ASSERT(this, IsWeakOrCleared(maybe_weak_ref));
    2604             :     TNode<PropertyCell> property_cell =
    2605         784 :         CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, try_handler));
    2606             :     TNode<Object> value =
    2607             :         LoadObjectField(property_cell, PropertyCell::kValueOffset);
    2608        1568 :     GotoIf(WordEqual(value, TheHoleConstant()), miss);
    2609         784 :     exit_point->Return(value);
    2610             :   }
    2611             : 
    2612         784 :   BIND(&if_lexical_var);
    2613             :   {
    2614         784 :     Comment("Load lexical variable");
    2615         784 :     TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
    2616             :     TNode<IntPtrT> context_index =
    2617         784 :         Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
    2618             :     TNode<IntPtrT> slot_index =
    2619             :         Signed(DecodeWord<FeedbackNexus::SlotIndexBits>(lexical_handler));
    2620         784 :     TNode<Context> context = lazy_context();
    2621         784 :     TNode<Context> script_context = LoadScriptContext(context, context_index);
    2622         784 :     TNode<Object> result = LoadContextElement(script_context, slot_index);
    2623         784 :     exit_point->Return(result);
    2624         784 :   }
    2625         784 : }
    2626             : 
    2627         784 : void AccessorAssembler::LoadGlobalIC_TryHandlerCase(
    2628             :     TNode<FeedbackVector> vector, Node* slot,
    2629             :     const LazyNode<Context>& lazy_context, const LazyNode<Name>& lazy_name,
    2630             :     TypeofMode typeof_mode, ExitPoint* exit_point, Label* miss,
    2631             :     ParameterMode slot_mode) {
    2632         784 :   Comment("LoadGlobalIC_TryHandlerCase");
    2633             : 
    2634         784 :   Label call_handler(this), non_smi(this);
    2635             : 
    2636             :   TNode<MaybeObject> feedback_element =
    2637         784 :       LoadFeedbackVectorSlot(vector, slot, kTaggedSize, slot_mode);
    2638             :   TNode<Object> handler = CAST(feedback_element);
    2639        1568 :   GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)), miss);
    2640             : 
    2641             :   OnNonExistent on_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF
    2642             :                                      ? OnNonExistent::kThrowReferenceError
    2643         784 :                                      : OnNonExistent::kReturnUndefined;
    2644             : 
    2645         784 :   TNode<Context> context = lazy_context();
    2646         784 :   TNode<Context> native_context = LoadNativeContext(context);
    2647             :   TNode<JSGlobalProxy> receiver =
    2648         784 :       CAST(LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX));
    2649        1568 :   Node* holder = LoadContextElement(native_context, Context::EXTENSION_INDEX);
    2650             : 
    2651             :   LoadICParameters p(context, receiver, lazy_name(),
    2652        1568 :                      ParameterToTagged(slot, slot_mode), vector, holder);
    2653             : 
    2654             :   HandleLoadICHandlerCase(&p, handler, miss, exit_point, ICMode::kGlobalIC,
    2655        1568 :                           on_nonexistent);
    2656         784 : }
    2657             : 
    2658          56 : void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) {
    2659          56 :   ExitPoint direct_exit(this);
    2660             : 
    2661          56 :   TVARIABLE(MaybeObject, var_handler);
    2662          56 :   Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred),
    2663          56 :       try_megamorphic(this, Label::kDeferred),
    2664          56 :       try_polymorphic_name(this, Label::kDeferred),
    2665          56 :       miss(this, Label::kDeferred);
    2666             : 
    2667         168 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2668         112 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2669             : 
    2670             :   // Check monomorphic case.
    2671             :   TNode<MaybeObject> feedback =
    2672             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2673          56 :                          &var_handler, &try_polymorphic);
    2674          56 :   BIND(&if_handler);
    2675             :   {
    2676             :     HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
    2677             :                             ICMode::kNonGlobalIC,
    2678          56 :                             OnNonExistent::kReturnUndefined, kSupportElements);
    2679             :   }
    2680             : 
    2681          56 :   BIND(&try_polymorphic);
    2682          56 :   TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    2683             :   {
    2684             :     // Check polymorphic case.
    2685          56 :     Comment("KeyedLoadIC_try_polymorphic");
    2686         168 :     GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
    2687             :     HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
    2688          56 :                           &var_handler, &miss, 2);
    2689             :   }
    2690             : 
    2691          56 :   BIND(&try_megamorphic);
    2692             :   {
    2693             :     // Check megamorphic case.
    2694          56 :     Comment("KeyedLoadIC_try_megamorphic");
    2695             :     GotoIfNot(
    2696          56 :         WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    2697          56 :         &try_polymorphic_name);
    2698             :     // TODO(jkummerow): Inline this? Or some of it?
    2699             :     TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, p->context, p->receiver,
    2700         112 :                     p->name, p->slot, p->vector);
    2701             :   }
    2702          56 :   BIND(&try_polymorphic_name);
    2703             :   {
    2704             :     // We might have a name in feedback, and a weak fixed array in the next
    2705             :     // slot.
    2706          56 :     Node* name = p->name;
    2707          56 :     Comment("KeyedLoadIC_try_polymorphic_name");
    2708          56 :     VARIABLE(var_name, MachineRepresentation::kTagged, name);
    2709         112 :     VARIABLE(var_index, MachineType::PointerRepresentation());
    2710          56 :     Label if_polymorphic_name(this, &var_name), if_internalized(this),
    2711          56 :         if_notinternalized(this, Label::kDeferred);
    2712             : 
    2713             :     // Fast-case: The recorded {feedback} matches the {name}.
    2714          56 :     GotoIf(WordEqual(strong_feedback, name), &if_polymorphic_name);
    2715             : 
    2716             :     // Try to internalize the {name} if it isn't already.
    2717             :     TryToName(name, &miss, &var_index, &if_internalized, &var_name, &miss,
    2718          56 :               &if_notinternalized);
    2719             : 
    2720          56 :     BIND(&if_internalized);
    2721             :     {
    2722             :       // The {var_name} now contains a unique name.
    2723          56 :       Branch(WordEqual(strong_feedback, var_name.value()), &if_polymorphic_name,
    2724          56 :              &miss);
    2725             :     }
    2726             : 
    2727          56 :     BIND(&if_notinternalized);
    2728             :     {
    2729             :       // Try to internalize the {name}.
    2730             :       Node* function = ExternalConstant(
    2731         112 :           ExternalReference::try_internalize_string_function());
    2732             :       Node* const isolate_ptr =
    2733         112 :           ExternalConstant(ExternalReference::isolate_address(isolate()));
    2734             :       var_name.Bind(CallCFunction2(
    2735             :           MachineType::AnyTagged(), MachineType::Pointer(),
    2736          56 :           MachineType::AnyTagged(), function, isolate_ptr, name));
    2737          56 :       Goto(&if_internalized);
    2738             :     }
    2739             : 
    2740          56 :     BIND(&if_polymorphic_name);
    2741             :     {
    2742             :       // If the name comparison succeeded, we know we have a weak fixed array
    2743             :       // with at least one map/handler pair.
    2744          56 :       Node* name = var_name.value();
    2745             :       TailCallBuiltin(Builtins::kKeyedLoadIC_PolymorphicName, p->context,
    2746         112 :                       p->receiver, name, p->slot, p->vector);
    2747          56 :     }
    2748             :   }
    2749             : 
    2750          56 :   BIND(&miss);
    2751             :   {
    2752          56 :     Comment("KeyedLoadIC_miss");
    2753             :     TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver,
    2754         112 :                     p->name, p->slot, p->vector);
    2755             :   }
    2756          56 : }
    2757             : 
    2758          56 : void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) {
    2759          56 :   VARIABLE(var_index, MachineType::PointerRepresentation());
    2760         112 :   VARIABLE(var_unique, MachineRepresentation::kTagged, p->name);
    2761          56 :   Label if_index(this), if_unique_name(this), if_notunique(this),
    2762          56 :       if_other(this, Label::kDeferred), if_runtime(this, Label::kDeferred);
    2763             : 
    2764          56 :   Node* receiver = p->receiver;
    2765         112 :   GotoIf(TaggedIsSmi(receiver), &if_runtime);
    2766             : 
    2767             :   TryToName(p->name, &if_index, &var_index, &if_unique_name, &var_unique,
    2768          56 :             &if_other, &if_notunique);
    2769             : 
    2770          56 :   BIND(&if_other);
    2771             :   {
    2772         168 :     Node* name = CallBuiltin(Builtins::kToName, p->context, p->name);
    2773          56 :     var_unique.Bind(name);
    2774             :     TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique,
    2775          56 :               &if_runtime, &if_notunique);
    2776             :   }
    2777             : 
    2778          56 :   BIND(&if_index);
    2779             :   {
    2780         112 :     Node* receiver_map = LoadMap(receiver);
    2781         112 :     Node* instance_type = LoadMapInstanceType(receiver_map);
    2782             :     GenericElementLoad(receiver, receiver_map, instance_type, var_index.value(),
    2783         112 :                        &if_runtime);
    2784             :   }
    2785             : 
    2786          56 :   BIND(&if_unique_name);
    2787             :   {
    2788          56 :     LoadICParameters pp = *p;
    2789          56 :     pp.name = var_unique.value();
    2790         112 :     Node* receiver_map = LoadMap(receiver);
    2791         112 :     Node* instance_type = LoadMapInstanceType(receiver_map);
    2792             :     GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
    2793          56 :                         &if_runtime);
    2794             :   }
    2795             : 
    2796          56 :   BIND(&if_notunique);
    2797             :   {
    2798             :     if (FLAG_internalize_on_the_fly) {
    2799             :       // Ideally we could return undefined directly here if the name is not
    2800             :       // found in the string table, i.e. it was never internalized, but that
    2801             :       // invariant doesn't hold with named property interceptors (at this
    2802             :       // point), so we take the {if_runtime} path instead.
    2803             :       Label if_in_string_table(this);
    2804             :       TryInternalizeString(var_unique.value(), &if_index, &var_index,
    2805             :                            &if_in_string_table, &var_unique, &if_runtime,
    2806          56 :                            &if_runtime);
    2807             : 
    2808          56 :       BIND(&if_in_string_table);
    2809             :       {
    2810             :         // TODO(bmeurer): We currently use a version of GenericPropertyLoad
    2811             :         // here, where we don't try to probe the megamorphic stub cache after
    2812             :         // successfully internalizing the incoming string. Past experiments
    2813             :         // with this have shown that it causes too much traffic on the stub
    2814             :         // cache. We may want to re-evaluate that in the future.
    2815          56 :         LoadICParameters pp = *p;
    2816          56 :         pp.name = var_unique.value();
    2817         112 :         Node* receiver_map = LoadMap(receiver);
    2818         112 :         Node* instance_type = LoadMapInstanceType(receiver_map);
    2819             :         GenericPropertyLoad(receiver, receiver_map, instance_type, &pp,
    2820          56 :                             &if_runtime, kDontUseStubCache);
    2821          56 :       }
    2822             :     } else {
    2823             :       Goto(&if_runtime);
    2824             :     }
    2825             :   }
    2826             : 
    2827          56 :   BIND(&if_runtime);
    2828             :   {
    2829          56 :     Comment("KeyedLoadGeneric_slow");
    2830         112 :     IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1);
    2831             :     // TODO(jkummerow): Should we use the GetProperty TF stub instead?
    2832             :     TailCallRuntime(Runtime::kGetProperty, p->context, p->receiver,
    2833         112 :                     var_unique.value());
    2834          56 :   }
    2835          56 : }
    2836             : 
    2837          56 : void AccessorAssembler::KeyedLoadICPolymorphicName(const LoadICParameters* p) {
    2838          56 :   TVARIABLE(MaybeObject, var_handler);
    2839          56 :   Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
    2840             : 
    2841          56 :   Node* receiver = p->receiver;
    2842         112 :   Node* receiver_map = LoadReceiverMap(receiver);
    2843          56 :   Node* name = p->name;
    2844          56 :   Node* vector = p->vector;
    2845          56 :   Node* slot = p->slot;
    2846          56 :   Node* context = p->context;
    2847             : 
    2848             :   // When we get here, we know that the {name} matches the recorded
    2849             :   // feedback name in the {vector} and can safely be used for the
    2850             :   // LoadIC handler logic below.
    2851             :   CSA_ASSERT(this, IsName(name));
    2852             :   CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map)));
    2853             :   CSA_ASSERT(this, WordEqual(name, CAST(LoadFeedbackVectorSlot(
    2854             :                                        vector, slot, 0, SMI_PARAMETERS))));
    2855             : 
    2856             :   // Check if we have a matching handler for the {receiver_map}.
    2857             :   TNode<MaybeObject> feedback_element =
    2858          56 :       LoadFeedbackVectorSlot(vector, slot, kTaggedSize, SMI_PARAMETERS);
    2859          56 :   TNode<WeakFixedArray> array = CAST(feedback_element);
    2860             :   HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss,
    2861          56 :                         1);
    2862             : 
    2863          56 :   BIND(&if_handler);
    2864             :   {
    2865             :     ExitPoint direct_exit(this);
    2866             :     HandleLoadICHandlerCase(p, CAST(var_handler.value()), &miss, &direct_exit,
    2867             :                             ICMode::kNonGlobalIC,
    2868          56 :                             OnNonExistent::kReturnUndefined, kOnlyProperties);
    2869             :   }
    2870             : 
    2871          56 :   BIND(&miss);
    2872             :   {
    2873          56 :     Comment("KeyedLoadIC_miss");
    2874             :     TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot,
    2875          56 :                     vector);
    2876             :   }
    2877          56 : }
    2878             : 
    2879          56 : void AccessorAssembler::StoreIC(const StoreICParameters* p) {
    2880         112 :   TVARIABLE(MaybeObject, var_handler,
    2881             :             ReinterpretCast<MaybeObject>(SmiConstant(0)));
    2882             : 
    2883          56 :   Label if_handler(this, &var_handler),
    2884          56 :       if_handler_from_stub_cache(this, &var_handler, Label::kDeferred),
    2885          56 :       try_polymorphic(this, Label::kDeferred),
    2886          56 :       try_megamorphic(this, Label::kDeferred),
    2887          56 :       try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred);
    2888             : 
    2889         168 :   Node* receiver_map = LoadReceiverMap(p->receiver);
    2890         112 :   GotoIf(IsDeprecatedMap(receiver_map), &miss);
    2891             : 
    2892             :   // Check monomorphic case.
    2893             :   TNode<MaybeObject> feedback =
    2894             :       TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    2895          56 :                          &var_handler, &try_polymorphic);
    2896          56 :   BIND(&if_handler);
    2897             :   {
    2898          56 :     Comment("StoreIC_if_handler");
    2899             :     HandleStoreICHandlerCase(p, var_handler.value(), &miss,
    2900          56 :                              ICMode::kNonGlobalIC);
    2901             :   }
    2902             : 
    2903          56 :   BIND(&try_polymorphic);
    2904          56 :   TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    2905             :   {
    2906             :     // Check polymorphic case.
    2907          56 :     Comment("StoreIC_try_polymorphic");
    2908         168 :     GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
    2909             :     HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
    2910          56 :                           &var_handler, &miss, 2);
    2911             :   }
    2912             : 
    2913          56 :   BIND(&try_megamorphic);
    2914             :   {
    2915             :     // Check megamorphic case.
    2916             :     GotoIfNot(
    2917          56 :         WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    2918          56 :         &try_uninitialized);
    2919             : 
    2920             :     TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name,
    2921          56 :                       &if_handler, &var_handler, &miss);
    2922             :   }
    2923          56 :   BIND(&try_uninitialized);
    2924             :   {
    2925             :     // Check uninitialized case.
    2926             :     GotoIfNot(
    2927          56 :         WordEqual(strong_feedback, LoadRoot(RootIndex::kuninitialized_symbol)),
    2928          56 :         &miss);
    2929             :     TailCallBuiltin(Builtins::kStoreIC_Uninitialized, p->context, p->receiver,
    2930         112 :                     p->name, p->value, p->slot, p->vector);
    2931             :   }
    2932          56 :   BIND(&miss);
    2933             :   {
    2934             :     TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot,
    2935         112 :                     p->vector, p->receiver, p->name);
    2936             :   }
    2937          56 : }
    2938             : 
    2939          56 : void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
    2940         112 :   Label if_lexical_var(this), if_property_cell(this);
    2941             :   TNode<MaybeObject> maybe_weak_ref =
    2942          56 :       LoadFeedbackVectorSlot(pp->vector, pp->slot, 0, SMI_PARAMETERS);
    2943         112 :   Branch(TaggedIsSmi(maybe_weak_ref), &if_lexical_var, &if_property_cell);
    2944             : 
    2945          56 :   BIND(&if_property_cell);
    2946             :   {
    2947          56 :     Label try_handler(this), miss(this, Label::kDeferred);
    2948             :     CSA_ASSERT(this, IsWeakOrCleared(maybe_weak_ref));
    2949             :     TNode<PropertyCell> property_cell =
    2950          56 :         CAST(GetHeapObjectAssumeWeak(maybe_weak_ref, &try_handler));
    2951             : 
    2952             :     ExitPoint direct_exit(this);
    2953             :     StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit,
    2954          56 :                                    &miss);
    2955             : 
    2956          56 :     BIND(&try_handler);
    2957             :     {
    2958          56 :       Comment("StoreGlobalIC_try_handler");
    2959             :       TNode<MaybeObject> handler = LoadFeedbackVectorSlot(
    2960          56 :           pp->vector, pp->slot, kTaggedSize, SMI_PARAMETERS);
    2961             : 
    2962          56 :       GotoIf(WordEqual(handler, LoadRoot(RootIndex::kuninitialized_symbol)),
    2963          56 :              &miss);
    2964             : 
    2965          56 :       StoreICParameters p = *pp;
    2966             :       DCHECK_NULL(p.receiver);
    2967         168 :       Node* native_context = LoadNativeContext(p.context);
    2968         112 :       p.receiver =
    2969         112 :           LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
    2970             : 
    2971          56 :       HandleStoreICHandlerCase(&p, handler, &miss, ICMode::kGlobalIC);
    2972             :     }
    2973             : 
    2974          56 :     BIND(&miss);
    2975             :     {
    2976             :       TailCallRuntime(Runtime::kStoreGlobalIC_Miss, pp->context, pp->value,
    2977         112 :                       pp->slot, pp->vector, pp->name);
    2978          56 :     }
    2979             :   }
    2980             : 
    2981          56 :   BIND(&if_lexical_var);
    2982             :   {
    2983          56 :     Comment("Store lexical variable");
    2984          56 :     TNode<IntPtrT> lexical_handler = SmiUntag(CAST(maybe_weak_ref));
    2985             :     TNode<IntPtrT> context_index =
    2986          56 :         Signed(DecodeWord<FeedbackNexus::ContextIndexBits>(lexical_handler));
    2987             :     TNode<IntPtrT> slot_index =
    2988             :         Signed(DecodeWord<FeedbackNexus::SlotIndexBits>(lexical_handler));
    2989             :     TNode<Context> script_context =
    2990          56 :         LoadScriptContext(CAST(pp->context), context_index);
    2991          56 :     StoreContextElement(script_context, slot_index, pp->value);
    2992          56 :     Return(pp->value);
    2993          56 :   }
    2994          56 : }
    2995             : 
    2996         392 : void AccessorAssembler::StoreGlobalIC_PropertyCellCase(Node* property_cell,
    2997             :                                                        Node* value,
    2998             :                                                        ExitPoint* exit_point,
    2999             :                                                        Label* miss) {
    3000         392 :   Comment("StoreGlobalIC_TryPropertyCellCase");
    3001             :   CSA_ASSERT(this, IsPropertyCell(property_cell));
    3002             : 
    3003             :   // Load the payload of the global parameter cell. A hole indicates that
    3004             :   // the cell has been invalidated and that the store must be handled by the
    3005             :   // runtime.
    3006             :   Node* cell_contents =
    3007         392 :       LoadObjectField(property_cell, PropertyCell::kValueOffset);
    3008             :   Node* details = LoadAndUntagToWord32ObjectField(property_cell,
    3009         784 :                                                   PropertyCell::kDetailsOffset);
    3010         784 :   GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask), miss);
    3011             :   CSA_ASSERT(this,
    3012             :              Word32Equal(DecodeWord32<PropertyDetails::KindField>(details),
    3013             :                          Int32Constant(kData)));
    3014             : 
    3015             :   Node* type = DecodeWord32<PropertyDetails::PropertyCellTypeField>(details);
    3016             : 
    3017         392 :   Label constant(this), store(this), not_smi(this);
    3018             : 
    3019             :   GotoIf(Word32Equal(type, Int32Constant(
    3020         784 :                                static_cast<int>(PropertyCellType::kConstant))),
    3021         784 :          &constant);
    3022             : 
    3023         784 :   GotoIf(IsTheHole(cell_contents), miss);
    3024             : 
    3025             :   GotoIf(Word32Equal(
    3026         784 :              type, Int32Constant(static_cast<int>(PropertyCellType::kMutable))),
    3027         784 :          &store);
    3028             :   CSA_ASSERT(this,
    3029             :              Word32Or(Word32Equal(type, Int32Constant(static_cast<int>(
    3030             :                                             PropertyCellType::kConstantType))),
    3031             :                       Word32Equal(type, Int32Constant(static_cast<int>(
    3032             :                                             PropertyCellType::kUndefined)))));
    3033             : 
    3034         784 :   GotoIfNot(TaggedIsSmi(cell_contents), &not_smi);
    3035         784 :   GotoIfNot(TaggedIsSmi(value), miss);
    3036         392 :   Goto(&store);
    3037             : 
    3038         392 :   BIND(&not_smi);
    3039             :   {
    3040         784 :     GotoIf(TaggedIsSmi(value), miss);
    3041         784 :     Node* expected_map = LoadMap(cell_contents);
    3042         784 :     Node* map = LoadMap(value);
    3043         784 :     GotoIfNot(WordEqual(expected_map, map), miss);
    3044         392 :     Goto(&store);
    3045             :   }
    3046             : 
    3047         392 :   BIND(&store);
    3048             :   {
    3049         392 :     StoreObjectField(property_cell, PropertyCell::kValueOffset, value);
    3050         392 :     exit_point->Return(value);
    3051             :   }
    3052             : 
    3053         392 :   BIND(&constant);
    3054             :   {
    3055         784 :     GotoIfNot(WordEqual(cell_contents, value), miss);
    3056         392 :     exit_point->Return(value);
    3057         392 :   }
    3058         392 : }
    3059             : 
    3060          56 : void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p) {
    3061          56 :   Label miss(this, Label::kDeferred);
    3062             :   {
    3063             :     TVARIABLE(MaybeObject, var_handler);
    3064             : 
    3065          56 :     Label if_handler(this, &var_handler),
    3066          56 :         try_polymorphic(this, Label::kDeferred),
    3067          56 :         try_megamorphic(this, Label::kDeferred),
    3068          56 :         try_polymorphic_name(this, Label::kDeferred);
    3069             : 
    3070         168 :     Node* receiver_map = LoadReceiverMap(p->receiver);
    3071         112 :     GotoIf(IsDeprecatedMap(receiver_map), &miss);
    3072             : 
    3073             :     // Check monomorphic case.
    3074             :     TNode<MaybeObject> feedback =
    3075             :         TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler,
    3076          56 :                            &var_handler, &try_polymorphic);
    3077          56 :     BIND(&if_handler);
    3078             :     {
    3079          56 :       Comment("KeyedStoreIC_if_handler");
    3080             :       HandleStoreICHandlerCase(p, var_handler.value(), &miss,
    3081          56 :                                ICMode::kNonGlobalIC, kSupportElements);
    3082             :     }
    3083             : 
    3084          56 :     BIND(&try_polymorphic);
    3085          56 :     TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    3086             :     {
    3087             :       // CheckPolymorphic case.
    3088          56 :       Comment("KeyedStoreIC_try_polymorphic");
    3089         112 :       GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
    3090         112 :                 &try_megamorphic);
    3091             :       HandlePolymorphicCase(receiver_map, CAST(strong_feedback), &if_handler,
    3092          56 :                             &var_handler, &miss, 2);
    3093             :     }
    3094             : 
    3095          56 :     BIND(&try_megamorphic);
    3096             :     {
    3097             :       // Check megamorphic case.
    3098          56 :       Comment("KeyedStoreIC_try_megamorphic");
    3099             :       GotoIfNot(
    3100          56 :           WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    3101          56 :           &try_polymorphic_name);
    3102             :       TailCallBuiltin(Builtins::kKeyedStoreIC_Megamorphic, p->context,
    3103         112 :                       p->receiver, p->name, p->value, p->slot, p->vector);
    3104             :     }
    3105             : 
    3106          56 :     BIND(&try_polymorphic_name);
    3107             :     {
    3108             :       // We might have a name in feedback, and a fixed array in the next slot.
    3109          56 :       Comment("KeyedStoreIC_try_polymorphic_name");
    3110         112 :       GotoIfNot(WordEqual(strong_feedback, p->name), &miss);
    3111             :       // If the name comparison succeeded, we know we have a feedback vector
    3112             :       // with at least one map/handler pair.
    3113             :       TNode<MaybeObject> feedback_element = LoadFeedbackVectorSlot(
    3114          56 :           p->vector, p->slot, kTaggedSize, SMI_PARAMETERS);
    3115          56 :       TNode<WeakFixedArray> array = CAST(feedback_element);
    3116             :       HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler,
    3117          56 :                             &miss, 1);
    3118             :     }
    3119             :   }
    3120          56 :   BIND(&miss);
    3121             :   {
    3122          56 :     Comment("KeyedStoreIC_miss");
    3123             :     TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
    3124         112 :                     p->vector, p->receiver, p->name);
    3125          56 :   }
    3126          56 : }
    3127             : 
    3128          56 : void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
    3129          56 :   Label miss(this, Label::kDeferred);
    3130             :   {
    3131             :     TVARIABLE(MaybeObject, var_handler);
    3132             : 
    3133          56 :     Label if_handler(this, &var_handler),
    3134          56 :         try_polymorphic(this, Label::kDeferred),
    3135          56 :         try_megamorphic(this, Label::kDeferred);
    3136             : 
    3137         168 :     Node* array_map = LoadReceiverMap(p->receiver);
    3138         112 :     GotoIf(IsDeprecatedMap(array_map), &miss);
    3139             :     TNode<MaybeObject> feedback =
    3140             :         TryMonomorphicCase(p->slot, p->vector, array_map, &if_handler,
    3141          56 :                            &var_handler, &try_polymorphic);
    3142             : 
    3143          56 :     BIND(&if_handler);
    3144             :     {
    3145          56 :       Comment("StoreInArrayLiteralIC_if_handler");
    3146             :       // This is a stripped-down version of HandleStoreICHandlerCase.
    3147             : 
    3148             :       TNode<HeapObject> handler = CAST(var_handler.value());
    3149             :       Label if_transitioning_element_store(this);
    3150         112 :       GotoIfNot(IsCode(handler), &if_transitioning_element_store);
    3151          56 :       TailCallStub(StoreWithVectorDescriptor{}, CAST(handler), CAST(p->context),
    3152         112 :                    p->receiver, p->name, p->value, p->slot, p->vector);
    3153             : 
    3154          56 :       BIND(&if_transitioning_element_store);
    3155             :       {
    3156             :         TNode<MaybeObject> maybe_transition_map =
    3157          56 :             LoadHandlerDataField(CAST(handler), 1);
    3158             :         TNode<Map> transition_map =
    3159          56 :             CAST(GetHeapObjectAssumeWeak(maybe_transition_map, &miss));
    3160         112 :         GotoIf(IsDeprecatedMap(transition_map), &miss);
    3161             :         Node* code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
    3162             :         CSA_ASSERT(this, IsCode(code));
    3163             :         TailCallStub(StoreTransitionDescriptor{}, code, p->context, p->receiver,
    3164         112 :                      p->name, transition_map, p->value, p->slot, p->vector);
    3165          56 :       }
    3166             :     }
    3167             : 
    3168          56 :     BIND(&try_polymorphic);
    3169          56 :     TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    3170             :     {
    3171          56 :       Comment("StoreInArrayLiteralIC_try_polymorphic");
    3172         112 :       GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)),
    3173         112 :                 &try_megamorphic);
    3174             :       HandlePolymorphicCase(array_map, CAST(strong_feedback), &if_handler,
    3175          56 :                             &var_handler, &miss, 2);
    3176             :     }
    3177             : 
    3178          56 :     BIND(&try_megamorphic);
    3179             :     {
    3180          56 :       Comment("StoreInArrayLiteralIC_try_megamorphic");
    3181             :       CSA_ASSERT(this,
    3182             :                  Word32Or(WordEqual(strong_feedback,
    3183             :                                     LoadRoot(RootIndex::kuninitialized_symbol)),
    3184             :                           WordEqual(strong_feedback,
    3185             :                                     LoadRoot(RootIndex::kmegamorphic_symbol))));
    3186             :       GotoIfNot(
    3187          56 :           WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    3188          56 :           &miss);
    3189             :       TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Slow, p->context,
    3190         112 :                       p->value, p->receiver, p->name);
    3191             :     }
    3192             :   }
    3193             : 
    3194          56 :   BIND(&miss);
    3195             :   {
    3196          56 :     Comment("StoreInArrayLiteralIC_miss");
    3197             :     TailCallRuntime(Runtime::kStoreInArrayLiteralIC_Miss, p->context, p->value,
    3198         112 :                     p->slot, p->vector, p->receiver, p->name);
    3199          56 :   }
    3200          56 : }
    3201             : 
    3202             : //////////////////// Public methods.
    3203             : 
    3204          56 : void AccessorAssembler::GenerateLoadIC() {
    3205             :   typedef LoadWithVectorDescriptor Descriptor;
    3206             : 
    3207          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3208          56 :   Node* name = Parameter(Descriptor::kName);
    3209          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3210          56 :   Node* vector = Parameter(Descriptor::kVector);
    3211          56 :   Node* context = Parameter(Descriptor::kContext);
    3212             : 
    3213             :   LoadICParameters p(context, receiver, name, slot, vector);
    3214          56 :   LoadIC(&p);
    3215          56 : }
    3216             : 
    3217          56 : void AccessorAssembler::GenerateLoadIC_Megamorphic() {
    3218             :   typedef LoadWithVectorDescriptor Descriptor;
    3219             : 
    3220          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3221          56 :   Node* name = Parameter(Descriptor::kName);
    3222          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3223          56 :   Node* vector = Parameter(Descriptor::kVector);
    3224          56 :   Node* context = Parameter(Descriptor::kContext);
    3225             : 
    3226          56 :   ExitPoint direct_exit(this);
    3227             :   TVARIABLE(MaybeObject, var_handler);
    3228          56 :   Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
    3229             : 
    3230             :   TryProbeStubCache(isolate()->load_stub_cache(), receiver, name, &if_handler,
    3231          56 :                     &var_handler, &miss);
    3232             : 
    3233          56 :   BIND(&if_handler);
    3234             :   LoadICParameters p(context, receiver, name, slot, vector);
    3235          56 :   HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit);
    3236             : 
    3237          56 :   BIND(&miss);
    3238             :   direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
    3239          56 :                                 slot, vector);
    3240          56 : }
    3241             : 
    3242          56 : void AccessorAssembler::GenerateLoadIC_Noninlined() {
    3243             :   typedef LoadWithVectorDescriptor Descriptor;
    3244             : 
    3245          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3246          56 :   Node* name = Parameter(Descriptor::kName);
    3247          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3248          56 :   Node* vector = Parameter(Descriptor::kVector);
    3249          56 :   Node* context = Parameter(Descriptor::kContext);
    3250             : 
    3251          56 :   ExitPoint direct_exit(this);
    3252             :   TVARIABLE(MaybeObject, var_handler);
    3253          56 :   Label if_handler(this, &var_handler), miss(this, Label::kDeferred);
    3254             : 
    3255         112 :   Node* receiver_map = LoadReceiverMap(receiver);
    3256             :   TNode<MaybeObject> feedback_element =
    3257          56 :       LoadFeedbackVectorSlot(vector, slot, 0, SMI_PARAMETERS);
    3258          56 :   TNode<HeapObject> feedback = CAST(feedback_element);
    3259             : 
    3260             :   LoadICParameters p(context, receiver, name, slot, vector);
    3261             :   LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler,
    3262          56 :                     &miss, &direct_exit);
    3263             : 
    3264          56 :   BIND(&if_handler);
    3265          56 :   HandleLoadICHandlerCase(&p, CAST(var_handler.value()), &miss, &direct_exit);
    3266             : 
    3267          56 :   BIND(&miss);
    3268             :   direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
    3269          56 :                                 slot, vector);
    3270          56 : }
    3271             : 
    3272          56 : void AccessorAssembler::GenerateLoadIC_Uninitialized() {
    3273             :   typedef LoadWithVectorDescriptor Descriptor;
    3274             : 
    3275          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3276          56 :   Node* name = Parameter(Descriptor::kName);
    3277          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3278          56 :   Node* vector = Parameter(Descriptor::kVector);
    3279          56 :   Node* context = Parameter(Descriptor::kContext);
    3280             : 
    3281             :   LoadICParameters p(context, receiver, name, slot, vector);
    3282          56 :   LoadIC_Uninitialized(&p);
    3283          56 : }
    3284             : 
    3285          56 : void AccessorAssembler::GenerateLoadICTrampoline() {
    3286             :   typedef LoadDescriptor Descriptor;
    3287             : 
    3288          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3289          56 :   Node* name = Parameter(Descriptor::kName);
    3290          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3291          56 :   Node* context = Parameter(Descriptor::kContext);
    3292         112 :   Node* vector = LoadFeedbackVectorForStub();
    3293             : 
    3294          56 :   TailCallBuiltin(Builtins::kLoadIC, context, receiver, name, slot, vector);
    3295          56 : }
    3296             : 
    3297          56 : void AccessorAssembler::GenerateLoadICTrampoline_Megamorphic() {
    3298             :   typedef LoadDescriptor Descriptor;
    3299             : 
    3300          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3301          56 :   Node* name = Parameter(Descriptor::kName);
    3302          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3303          56 :   Node* context = Parameter(Descriptor::kContext);
    3304         112 :   Node* vector = LoadFeedbackVectorForStub();
    3305             : 
    3306             :   TailCallBuiltin(Builtins::kLoadIC_Megamorphic, context, receiver, name, slot,
    3307          56 :                   vector);
    3308          56 : }
    3309             : 
    3310         112 : void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) {
    3311             :   typedef LoadGlobalWithVectorDescriptor Descriptor;
    3312             : 
    3313         112 :   Node* name = Parameter(Descriptor::kName);
    3314         112 :   Node* slot = Parameter(Descriptor::kSlot);
    3315         112 :   Node* vector = Parameter(Descriptor::kVector);
    3316         112 :   Node* context = Parameter(Descriptor::kContext);
    3317             : 
    3318         112 :   ExitPoint direct_exit(this);
    3319             :   LoadGlobalIC(CAST(vector), slot,
    3320             :                // lazy_context
    3321             :                [=] { return CAST(context); },
    3322             :                // lazy_name
    3323         336 :                [=] { return CAST(name); }, typeof_mode, &direct_exit);
    3324         112 : }
    3325             : 
    3326         112 : void AccessorAssembler::GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode) {
    3327             :   typedef LoadGlobalDescriptor Descriptor;
    3328             : 
    3329         112 :   Node* name = Parameter(Descriptor::kName);
    3330         112 :   Node* slot = Parameter(Descriptor::kSlot);
    3331         112 :   Node* context = Parameter(Descriptor::kContext);
    3332         224 :   Node* vector = LoadFeedbackVectorForStub();
    3333             : 
    3334             :   Callable callable =
    3335         112 :       CodeFactory::LoadGlobalICInOptimizedCode(isolate(), typeof_mode);
    3336         112 :   TailCallStub(callable, context, name, slot, vector);
    3337         112 : }
    3338             : 
    3339          56 : void AccessorAssembler::GenerateKeyedLoadIC() {
    3340             :   typedef LoadWithVectorDescriptor Descriptor;
    3341             : 
    3342          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3343          56 :   Node* name = Parameter(Descriptor::kName);
    3344          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3345          56 :   Node* vector = Parameter(Descriptor::kVector);
    3346          56 :   Node* context = Parameter(Descriptor::kContext);
    3347             : 
    3348             :   LoadICParameters p(context, receiver, name, slot, vector);
    3349          56 :   KeyedLoadIC(&p);
    3350          56 : }
    3351             : 
    3352          56 : void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() {
    3353             :   typedef LoadWithVectorDescriptor Descriptor;
    3354             : 
    3355          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3356          56 :   Node* name = Parameter(Descriptor::kName);
    3357          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3358          56 :   Node* vector = Parameter(Descriptor::kVector);
    3359          56 :   Node* context = Parameter(Descriptor::kContext);
    3360             : 
    3361             :   LoadICParameters p(context, receiver, name, slot, vector);
    3362          56 :   KeyedLoadICGeneric(&p);
    3363          56 : }
    3364             : 
    3365          56 : void AccessorAssembler::GenerateKeyedLoadICTrampoline() {
    3366             :   typedef LoadDescriptor Descriptor;
    3367             : 
    3368          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3369          56 :   Node* name = Parameter(Descriptor::kName);
    3370          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3371          56 :   Node* context = Parameter(Descriptor::kContext);
    3372         112 :   Node* vector = LoadFeedbackVectorForStub();
    3373             : 
    3374             :   TailCallBuiltin(Builtins::kKeyedLoadIC, context, receiver, name, slot,
    3375          56 :                   vector);
    3376          56 : }
    3377             : 
    3378          56 : void AccessorAssembler::GenerateKeyedLoadICTrampoline_Megamorphic() {
    3379             :   typedef LoadDescriptor Descriptor;
    3380             : 
    3381          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3382          56 :   Node* name = Parameter(Descriptor::kName);
    3383          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3384          56 :   Node* context = Parameter(Descriptor::kContext);
    3385         112 :   Node* vector = LoadFeedbackVectorForStub();
    3386             : 
    3387             :   TailCallBuiltin(Builtins::kKeyedLoadIC_Megamorphic, context, receiver, name,
    3388          56 :                   slot, vector);
    3389          56 : }
    3390             : 
    3391          56 : void AccessorAssembler::GenerateKeyedLoadIC_PolymorphicName() {
    3392             :   typedef LoadWithVectorDescriptor Descriptor;
    3393             : 
    3394          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3395          56 :   Node* name = Parameter(Descriptor::kName);
    3396          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3397          56 :   Node* vector = Parameter(Descriptor::kVector);
    3398          56 :   Node* context = Parameter(Descriptor::kContext);
    3399             : 
    3400             :   LoadICParameters p(context, receiver, name, slot, vector);
    3401          56 :   KeyedLoadICPolymorphicName(&p);
    3402          56 : }
    3403             : 
    3404          56 : void AccessorAssembler::GenerateStoreGlobalIC() {
    3405             :   typedef StoreGlobalWithVectorDescriptor Descriptor;
    3406             : 
    3407          56 :   Node* name = Parameter(Descriptor::kName);
    3408          56 :   Node* value = Parameter(Descriptor::kValue);
    3409          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3410          56 :   Node* vector = Parameter(Descriptor::kVector);
    3411          56 :   Node* context = Parameter(Descriptor::kContext);
    3412             : 
    3413             :   StoreICParameters p(context, nullptr, name, value, slot, vector);
    3414          56 :   StoreGlobalIC(&p);
    3415          56 : }
    3416             : 
    3417          56 : void AccessorAssembler::GenerateStoreGlobalICTrampoline() {
    3418             :   typedef StoreGlobalDescriptor Descriptor;
    3419             : 
    3420          56 :   Node* name = Parameter(Descriptor::kName);
    3421          56 :   Node* value = Parameter(Descriptor::kValue);
    3422          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3423          56 :   Node* context = Parameter(Descriptor::kContext);
    3424         112 :   Node* vector = LoadFeedbackVectorForStub();
    3425             : 
    3426          56 :   TailCallBuiltin(Builtins::kStoreGlobalIC, context, name, value, slot, vector);
    3427          56 : }
    3428             : 
    3429          56 : void AccessorAssembler::GenerateStoreIC() {
    3430             :   typedef StoreWithVectorDescriptor Descriptor;
    3431             : 
    3432          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3433          56 :   Node* name = Parameter(Descriptor::kName);
    3434          56 :   Node* value = Parameter(Descriptor::kValue);
    3435          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3436          56 :   Node* vector = Parameter(Descriptor::kVector);
    3437          56 :   Node* context = Parameter(Descriptor::kContext);
    3438             : 
    3439             :   StoreICParameters p(context, receiver, name, value, slot, vector);
    3440          56 :   StoreIC(&p);
    3441          56 : }
    3442             : 
    3443          56 : void AccessorAssembler::GenerateStoreICTrampoline() {
    3444             :   typedef StoreDescriptor Descriptor;
    3445             : 
    3446          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3447          56 :   Node* name = Parameter(Descriptor::kName);
    3448          56 :   Node* value = Parameter(Descriptor::kValue);
    3449          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3450          56 :   Node* context = Parameter(Descriptor::kContext);
    3451         112 :   Node* vector = LoadFeedbackVectorForStub();
    3452             : 
    3453             :   TailCallBuiltin(Builtins::kStoreIC, context, receiver, name, value, slot,
    3454          56 :                   vector);
    3455          56 : }
    3456             : 
    3457          56 : void AccessorAssembler::GenerateKeyedStoreIC() {
    3458             :   typedef StoreWithVectorDescriptor Descriptor;
    3459             : 
    3460          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3461          56 :   Node* name = Parameter(Descriptor::kName);
    3462          56 :   Node* value = Parameter(Descriptor::kValue);
    3463          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3464          56 :   Node* vector = Parameter(Descriptor::kVector);
    3465          56 :   Node* context = Parameter(Descriptor::kContext);
    3466             : 
    3467             :   StoreICParameters p(context, receiver, name, value, slot, vector);
    3468          56 :   KeyedStoreIC(&p);
    3469          56 : }
    3470             : 
    3471          56 : void AccessorAssembler::GenerateKeyedStoreICTrampoline() {
    3472             :   typedef StoreDescriptor Descriptor;
    3473             : 
    3474          56 :   Node* receiver = Parameter(Descriptor::kReceiver);
    3475          56 :   Node* name = Parameter(Descriptor::kName);
    3476          56 :   Node* value = Parameter(Descriptor::kValue);
    3477          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3478          56 :   Node* context = Parameter(Descriptor::kContext);
    3479         112 :   Node* vector = LoadFeedbackVectorForStub();
    3480             : 
    3481             :   TailCallBuiltin(Builtins::kKeyedStoreIC, context, receiver, name, value, slot,
    3482          56 :                   vector);
    3483          56 : }
    3484             : 
    3485          56 : void AccessorAssembler::GenerateStoreInArrayLiteralIC() {
    3486             :   typedef StoreWithVectorDescriptor Descriptor;
    3487             : 
    3488          56 :   Node* array = Parameter(Descriptor::kReceiver);
    3489          56 :   Node* index = Parameter(Descriptor::kName);
    3490          56 :   Node* value = Parameter(Descriptor::kValue);
    3491          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3492          56 :   Node* vector = Parameter(Descriptor::kVector);
    3493          56 :   Node* context = Parameter(Descriptor::kContext);
    3494             : 
    3495             :   StoreICParameters p(context, array, index, value, slot, vector);
    3496          56 :   StoreInArrayLiteralIC(&p);
    3497          56 : }
    3498             : 
    3499          56 : void AccessorAssembler::GenerateCloneObjectIC_Slow() {
    3500             :   typedef CloneObjectWithVectorDescriptor Descriptor;
    3501          56 :   TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
    3502          56 :   TNode<Smi> flags = CAST(Parameter(Descriptor::kFlags));
    3503          56 :   TNode<Context> context = CAST(Parameter(Descriptor::kContext));
    3504             : 
    3505             :   // The Slow case uses the same call interface as CloneObjectIC, so that it
    3506             :   // can be tail called from it. However, the feedback slot and vector are not
    3507             :   // used.
    3508             : 
    3509          56 :   TNode<Context> native_context = LoadNativeContext(context);
    3510             :   TNode<JSFunction> object_fn =
    3511          56 :       CAST(LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX));
    3512             :   TNode<Map> initial_map = CAST(
    3513             :       LoadObjectField(object_fn, JSFunction::kPrototypeOrInitialMapOffset));
    3514             :   CSA_ASSERT(this, IsMap(initial_map));
    3515             : 
    3516          56 :   TNode<JSObject> result = CAST(AllocateJSObjectFromMap(initial_map));
    3517             : 
    3518             :   {
    3519             :     Label did_set_proto_if_needed(this);
    3520             :     TNode<BoolT> is_null_proto = SmiNotEqual(
    3521             :         SmiAnd(flags, SmiConstant(ObjectLiteral::kHasNullPrototype)),
    3522         112 :         SmiConstant(Smi::zero()));
    3523          56 :     GotoIfNot(is_null_proto, &did_set_proto_if_needed);
    3524             : 
    3525             :     CallRuntime(Runtime::kInternalSetPrototype, context, result,
    3526          56 :                 NullConstant());
    3527             : 
    3528          56 :     Goto(&did_set_proto_if_needed);
    3529          56 :     BIND(&did_set_proto_if_needed);
    3530             :   }
    3531             : 
    3532         112 :   ReturnIf(IsNullOrUndefined(source), result);
    3533             : 
    3534             :   CSA_ASSERT(this, IsJSReceiver(source));
    3535             : 
    3536             :   Label call_runtime(this, Label::kDeferred);
    3537          56 :   Label done(this);
    3538             : 
    3539          56 :   TNode<Map> map = LoadMap(source);
    3540          56 :   TNode<Int32T> type = LoadMapInstanceType(map);
    3541             :   {
    3542             :     Label cont(this);
    3543         112 :     GotoIf(IsJSObjectInstanceType(type), &cont);
    3544         112 :     GotoIfNot(IsStringInstanceType(type), &done);
    3545          56 :     Branch(SmiEqual(LoadStringLengthAsSmi(CAST(source)), SmiConstant(0)), &done,
    3546         112 :            &call_runtime);
    3547          56 :     BIND(&cont);
    3548             :   }
    3549             : 
    3550         112 :   GotoIfNot(IsEmptyFixedArray(LoadElements(CAST(source))), &call_runtime);
    3551             : 
    3552             :   ForEachEnumerableOwnProperty(context, map, CAST(source),
    3553          56 :                                [=](TNode<Name> key, TNode<Object> value) {
    3554             :                                  SetPropertyInLiteral(context, result, key,
    3555          56 :                                                       value);
    3556          56 :                                },
    3557         112 :                                &call_runtime);
    3558          56 :   Goto(&done);
    3559             : 
    3560          56 :   BIND(&call_runtime);
    3561             :   CallRuntime(Runtime::kCopyDataProperties, context, result, source);
    3562             : 
    3563          56 :   Goto(&done);
    3564          56 :   BIND(&done);
    3565         112 :   Return(result);
    3566          56 : }
    3567             : 
    3568          56 : void AccessorAssembler::GenerateCloneObjectIC() {
    3569             :   typedef CloneObjectWithVectorDescriptor Descriptor;
    3570          56 :   TNode<HeapObject> source = CAST(Parameter(Descriptor::kSource));
    3571          56 :   Node* flags = Parameter(Descriptor::kFlags);
    3572          56 :   Node* slot = Parameter(Descriptor::kSlot);
    3573          56 :   Node* vector = Parameter(Descriptor::kVector);
    3574          56 :   Node* context = Parameter(Descriptor::kContext);
    3575             :   TVARIABLE(MaybeObject, var_handler);
    3576          56 :   Label if_handler(this, &var_handler);
    3577          56 :   Label miss(this, Label::kDeferred), try_polymorphic(this, Label::kDeferred),
    3578          56 :       try_megamorphic(this, Label::kDeferred);
    3579             : 
    3580          56 :   TNode<Map> source_map = LoadMap(UncheckedCast<HeapObject>(source));
    3581         112 :   GotoIf(IsDeprecatedMap(source_map), &miss);
    3582             :   TNode<MaybeObject> feedback = TryMonomorphicCase(
    3583          56 :       slot, vector, source_map, &if_handler, &var_handler, &try_polymorphic);
    3584             : 
    3585          56 :   BIND(&if_handler);
    3586             :   {
    3587          56 :     Comment("CloneObjectIC_if_handler");
    3588             : 
    3589             :     // Handlers for the CloneObjectIC stub are weak references to the Map of
    3590             :     // a result object.
    3591             :     TNode<Map> result_map = CAST(var_handler.value());
    3592         112 :     TVARIABLE(Object, var_properties, EmptyFixedArrayConstant());
    3593         112 :     TVARIABLE(FixedArrayBase, var_elements, EmptyFixedArrayConstant());
    3594             : 
    3595          56 :     Label allocate_object(this);
    3596         112 :     GotoIf(IsNullOrUndefined(source), &allocate_object);
    3597             :     CSA_SLOW_ASSERT(this, IsJSObjectMap(result_map));
    3598             : 
    3599             :     // The IC fast case should only be taken if the result map a compatible
    3600             :     // elements kind with the source object.
    3601             :     TNode<FixedArrayBase> source_elements = LoadElements(CAST(source));
    3602             : 
    3603             :     auto flags = ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW;
    3604         112 :     var_elements = CAST(CloneFixedArray(source_elements, flags));
    3605             : 
    3606             :     // Copy the PropertyArray backing store. The source PropertyArray must be
    3607             :     // either an Smi, or a PropertyArray.
    3608             :     // FIXME: Make a CSA macro for this
    3609             :     TNode<Object> source_properties =
    3610             :         LoadObjectField(source, JSObject::kPropertiesOrHashOffset);
    3611             :     {
    3612         112 :       GotoIf(TaggedIsSmi(source_properties), &allocate_object);
    3613         112 :       GotoIf(IsEmptyFixedArray(source_properties), &allocate_object);
    3614             : 
    3615             :       // This IC requires that the source object has fast properties
    3616             :       CSA_SLOW_ASSERT(this, IsPropertyArray(CAST(source_properties)));
    3617             :       TNode<IntPtrT> length = LoadPropertyArrayLength(
    3618          56 :           UncheckedCast<PropertyArray>(source_properties));
    3619         168 :       GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &allocate_object);
    3620             : 
    3621             :       auto mode = INTPTR_PARAMETERS;
    3622         112 :       var_properties = CAST(AllocatePropertyArray(length, mode));
    3623             :       FillPropertyArrayWithUndefined(var_properties.value(), IntPtrConstant(0),
    3624         112 :                                      length, mode);
    3625             :       CopyPropertyArrayValues(source_properties, var_properties.value(), length,
    3626          56 :                               SKIP_WRITE_BARRIER, mode, DestroySource::kNo);
    3627             :     }
    3628             : 
    3629          56 :     Goto(&allocate_object);
    3630          56 :     BIND(&allocate_object);
    3631             :     TNode<JSObject> object = UncheckedCast<JSObject>(AllocateJSObjectFromMap(
    3632          56 :         result_map, var_properties.value(), var_elements.value()));
    3633         112 :     ReturnIf(IsNullOrUndefined(source), object);
    3634             : 
    3635             :     // Lastly, clone any in-object properties.
    3636             :     // Determine the inobject property capacity of both objects, and copy the
    3637             :     // smaller number into the resulting object.
    3638             :     TNode<IntPtrT> source_start =
    3639          56 :         LoadMapInobjectPropertiesStartInWords(source_map);
    3640          56 :     TNode<IntPtrT> source_size = LoadMapInstanceSizeInWords(source_map);
    3641             :     TNode<IntPtrT> result_start =
    3642          56 :         LoadMapInobjectPropertiesStartInWords(result_map);
    3643             :     TNode<IntPtrT> field_offset_difference =
    3644             :         TimesTaggedSize(IntPtrSub(result_start, source_start));
    3645             : 
    3646             :     // If MutableHeapNumbers may be present in-object, allocations may occur
    3647             :     // within this loop, thus the write barrier is required.
    3648             :     //
    3649             :     // TODO(caitp): skip the write barrier until the first MutableHeapNumber
    3650             :     // field is found
    3651             :     const bool may_use_mutable_heap_numbers = !FLAG_unbox_double_fields;
    3652             : 
    3653             :     BuildFastLoop(
    3654             :         source_start, source_size,
    3655          56 :         [=](Node* field_index) {
    3656             :           TNode<IntPtrT> field_offset =
    3657          56 :               TimesTaggedSize(UncheckedCast<IntPtrT>(field_index));
    3658             : 
    3659             :           if (may_use_mutable_heap_numbers) {
    3660             :             TNode<Object> field = LoadObjectField(source, field_offset);
    3661             :             field = CloneIfMutablePrimitive(field);
    3662             :             TNode<IntPtrT> result_offset =
    3663             :                 IntPtrAdd(field_offset, field_offset_difference);
    3664             :             StoreObjectField(object, result_offset, field);
    3665             :           } else {
    3666             :             // Copy fields as raw data.
    3667             :             TNode<IntPtrT> field =
    3668          56 :                 LoadObjectField<IntPtrT>(source, field_offset);
    3669             :             TNode<IntPtrT> result_offset =
    3670          56 :                 IntPtrAdd(field_offset, field_offset_difference);
    3671          56 :             StoreObjectFieldNoWriteBarrier(object, result_offset, field);
    3672             :           }
    3673          56 :         },
    3674         112 :         1, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
    3675          56 :     Return(object);
    3676             :   }
    3677             : 
    3678          56 :   BIND(&try_polymorphic);
    3679          56 :   TNode<HeapObject> strong_feedback = GetHeapObjectIfStrong(feedback, &miss);
    3680             :   {
    3681          56 :     Comment("CloneObjectIC_try_polymorphic");
    3682         168 :     GotoIfNot(IsWeakFixedArrayMap(LoadMap(strong_feedback)), &try_megamorphic);
    3683             :     HandlePolymorphicCase(source_map, CAST(strong_feedback), &if_handler,
    3684          56 :                           &var_handler, &miss, 2);
    3685             :   }
    3686             : 
    3687          56 :   BIND(&try_megamorphic);
    3688             :   {
    3689          56 :     Comment("CloneObjectIC_try_megamorphic");
    3690             :     CSA_ASSERT(this,
    3691             :                Word32Or(WordEqual(strong_feedback,
    3692             :                                   LoadRoot(RootIndex::kuninitialized_symbol)),
    3693             :                         WordEqual(strong_feedback,
    3694             :                                   LoadRoot(RootIndex::kmegamorphic_symbol))));
    3695             :     GotoIfNot(
    3696          56 :         WordEqual(strong_feedback, LoadRoot(RootIndex::kmegamorphic_symbol)),
    3697          56 :         &miss);
    3698             :     TailCallBuiltin(Builtins::kCloneObjectIC_Slow, context, source, flags, slot,
    3699          56 :                     vector);
    3700             :   }
    3701             : 
    3702          56 :   BIND(&miss);
    3703             :   {
    3704          56 :     Comment("CloneObjectIC_miss");
    3705             :     Node* map_or_result = CallRuntime(Runtime::kCloneObjectIC_Miss, context,
    3706             :                                       source, flags, slot, vector);
    3707             :     var_handler = UncheckedCast<MaybeObject>(map_or_result);
    3708         112 :     GotoIf(IsMap(map_or_result), &if_handler);
    3709             :     CSA_ASSERT(this, IsJSObject(map_or_result));
    3710          56 :     Return(map_or_result);
    3711             :   }
    3712          56 : }
    3713             : 
    3714             : }  // namespace internal
    3715       94089 : }  // namespace v8

Generated by: LCOV version 1.10