LCOV - code coverage report
Current view: top level - src/ic - accessor-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1840 1849 99.5 %
Date: 2019-02-19 Functions: 91 92 98.9 %

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

Generated by: LCOV version 1.10