LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2102 2112 99.5 %
Date: 2019-03-21 Functions: 97 98 99.0 %

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

Generated by: LCOV version 1.10