LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1913 1923 99.5 %
Date: 2019-04-19 Functions: 87 89 97.8 %

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

Generated by: LCOV version 1.10