LCOV - code coverage report
Current view: top level - src - code-stub-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 454 462 98.3 %
Date: 2019-03-21 Functions: 573 603 95.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_CODE_STUB_ASSEMBLER_H_
       6             : #define V8_CODE_STUB_ASSEMBLER_H_
       7             : 
       8             : #include <functional>
       9             : 
      10             : #include "src/bailout-reason.h"
      11             : #include "src/base/macros.h"
      12             : #include "src/compiler/code-assembler.h"
      13             : #include "src/frames.h"
      14             : #include "src/globals.h"
      15             : #include "src/message-template.h"
      16             : #include "src/objects.h"
      17             : #include "src/objects/arguments.h"
      18             : #include "src/objects/bigint.h"
      19             : #include "src/objects/shared-function-info.h"
      20             : #include "src/objects/smi.h"
      21             : #include "src/roots.h"
      22             : 
      23             : #include "torque-generated/builtins-base-from-dsl-gen.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : 
      28             : class CallInterfaceDescriptor;
      29             : class CodeStubArguments;
      30             : class CodeStubAssembler;
      31             : class StatsCounter;
      32             : class StubCache;
      33             : 
      34             : enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
      35             : 
      36             : #define HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V)                              \
      37             :   V(ArraySpeciesProtector, array_species_protector, ArraySpeciesProtector) \
      38             :   V(PromiseSpeciesProtector, promise_species_protector,                    \
      39             :     PromiseSpeciesProtector)                                               \
      40             :   V(TypedArraySpeciesProtector, typed_array_species_protector,             \
      41             :     TypedArraySpeciesProtector)                                            \
      42             :   V(RegExpSpeciesProtector, regexp_species_protector, RegExpSpeciesProtector)
      43             : 
      44             : #define HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V)                                \
      45             :   V(AccessorInfoMap, accessor_info_map, AccessorInfoMap)                       \
      46             :   V(AccessorPairMap, accessor_pair_map, AccessorPairMap)                       \
      47             :   V(AllocationSiteWithWeakNextMap, allocation_site_map, AllocationSiteMap)     \
      48             :   V(AllocationSiteWithoutWeakNextMap, allocation_site_without_weaknext_map,    \
      49             :     AllocationSiteWithoutWeakNextMap)                                          \
      50             :   V(BooleanMap, boolean_map, BooleanMap)                                       \
      51             :   V(CodeMap, code_map, CodeMap)                                                \
      52             :   V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray)                       \
      53             :   V(EmptyPropertyDictionary, empty_property_dictionary,                        \
      54             :     EmptyPropertyDictionary)                                                   \
      55             :   V(EmptySlowElementDictionary, empty_slow_element_dictionary,                 \
      56             :     EmptySlowElementDictionary)                                                \
      57             :   V(empty_string, empty_string, EmptyString)                                   \
      58             :   V(FalseValue, false_value, False)                                            \
      59             :   V(FeedbackVectorMap, feedback_vector_map, FeedbackVectorMap)                 \
      60             :   V(FixedArrayMap, fixed_array_map, FixedArrayMap)                             \
      61             :   V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap)                   \
      62             :   V(FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArrayMap)          \
      63             :   V(FunctionTemplateInfoMap, function_template_info_map,                       \
      64             :     FunctionTemplateInfoMap)                                                   \
      65             :   V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap)          \
      66             :   V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol)               \
      67             :   V(HeapNumberMap, heap_number_map, HeapNumberMap)                             \
      68             :   V(iterator_symbol, iterator_symbol, IteratorSymbol)                          \
      69             :   V(length_string, length_string, LengthString)                                \
      70             :   V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap)          \
      71             :   V(MetaMap, meta_map, MetaMap)                                                \
      72             :   V(MinusZeroValue, minus_zero_value, MinusZero)                               \
      73             :   V(MutableHeapNumberMap, mutable_heap_number_map, MutableHeapNumberMap)       \
      74             :   V(NanValue, nan_value, Nan)                                                  \
      75             :   V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap)                \
      76             :   V(NullValue, null_value, Null)                                               \
      77             :   V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap)                \
      78             :   V(PreparseDataMap, preparse_data_map, PreparseDataMap)                       \
      79             :   V(prototype_string, prototype_string, PrototypeString)                       \
      80             :   V(SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfoMap)    \
      81             :   V(StoreHandler0Map, store_handler0_map, StoreHandler0Map)                    \
      82             :   V(SymbolMap, symbol_map, SymbolMap)                                          \
      83             :   V(TheHoleValue, the_hole_value, TheHole)                                     \
      84             :   V(TransitionArrayMap, transition_array_map, TransitionArrayMap)              \
      85             :   V(TrueValue, true_value, True)                                               \
      86             :   V(Tuple2Map, tuple2_map, Tuple2Map)                                          \
      87             :   V(Tuple3Map, tuple3_map, Tuple3Map)                                          \
      88             :   V(ArrayBoilerplateDescriptionMap, array_boilerplate_description_map,         \
      89             :     ArrayBoilerplateDescriptionMap)                                            \
      90             :   V(UncompiledDataWithoutPreparseDataMap,                                      \
      91             :     uncompiled_data_without_preparse_data_map,                                 \
      92             :     UncompiledDataWithoutPreparseDataMap)                                      \
      93             :   V(UncompiledDataWithPreparseDataMap, uncompiled_data_with_preparse_data_map, \
      94             :     UncompiledDataWithPreparseDataMap)                                         \
      95             :   V(UndefinedValue, undefined_value, Undefined)                                \
      96             :   V(WeakFixedArrayMap, weak_fixed_array_map, WeakFixedArrayMap)
      97             : 
      98             : #define HEAP_IMMOVABLE_OBJECT_LIST(V)   \
      99             :   HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \
     100             :   HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V)
     101             : 
     102             : #ifdef DEBUG
     103             : #define CSA_CHECK(csa, x)                                        \
     104             :   (csa)->Check(                                                  \
     105             :       [&]() -> compiler::Node* {                                 \
     106             :         return implicit_cast<compiler::SloppyTNode<Word32T>>(x); \
     107             :       },                                                         \
     108             :       #x, __FILE__, __LINE__)
     109             : #else
     110             : #define CSA_CHECK(csa, x) (csa)->FastCheck(x)
     111             : #endif
     112             : 
     113             : #ifdef DEBUG
     114             : // Add stringified versions to the given values, except the first. That is,
     115             : // transform
     116             : //   x, a, b, c, d, e, f
     117             : // to
     118             : //   a, "a", b, "b", c, "c", d, "d", e, "e", f, "f"
     119             : //
     120             : // __VA_ARGS__  is ignored to allow the caller to pass through too many
     121             : // parameters, and the first element is ignored to support having no extra
     122             : // values without empty __VA_ARGS__ (which cause all sorts of problems with
     123             : // extra commas).
     124             : #define CSA_ASSERT_STRINGIFY_EXTRA_VALUES_5(_, v1, v2, v3, v4, v5, ...) \
     125             :   v1, #v1, v2, #v2, v3, #v3, v4, #v4, v5, #v5
     126             : 
     127             : // Stringify the given variable number of arguments. The arguments are trimmed
     128             : // to 5 if there are too many, and padded with nullptr if there are not enough.
     129             : #define CSA_ASSERT_STRINGIFY_EXTRA_VALUES(...)                                \
     130             :   CSA_ASSERT_STRINGIFY_EXTRA_VALUES_5(__VA_ARGS__, nullptr, nullptr, nullptr, \
     131             :                                       nullptr, nullptr)
     132             : 
     133             : #define CSA_ASSERT_GET_FIRST(x, ...) (x)
     134             : #define CSA_ASSERT_GET_FIRST_STR(x, ...) #x
     135             : 
     136             : // CSA_ASSERT(csa, <condition>, <extra values to print...>)
     137             : 
     138             : // We have to jump through some hoops to allow <extra values to print...> to be
     139             : // empty.
     140             : #define CSA_ASSERT(csa, ...)                                             \
     141             :   (csa)->Assert(                                                         \
     142             :       [&]() -> compiler::Node* {                                         \
     143             :         return implicit_cast<compiler::SloppyTNode<Word32T>>(            \
     144             :             EXPAND(CSA_ASSERT_GET_FIRST(__VA_ARGS__)));                  \
     145             :       },                                                                 \
     146             :       EXPAND(CSA_ASSERT_GET_FIRST_STR(__VA_ARGS__)), __FILE__, __LINE__, \
     147             :       CSA_ASSERT_STRINGIFY_EXTRA_VALUES(__VA_ARGS__))
     148             : 
     149             : // CSA_ASSERT_BRANCH(csa, [](Label* ok, Label* not_ok) {...},
     150             : //     <extra values to print...>)
     151             : 
     152             : #define CSA_ASSERT_BRANCH(csa, ...)                                      \
     153             :   (csa)->Assert(EXPAND(CSA_ASSERT_GET_FIRST(__VA_ARGS__)),               \
     154             :                 EXPAND(CSA_ASSERT_GET_FIRST_STR(__VA_ARGS__)), __FILE__, \
     155             :                 __LINE__, CSA_ASSERT_STRINGIFY_EXTRA_VALUES(__VA_ARGS__))
     156             : 
     157             : #define CSA_ASSERT_JS_ARGC_OP(csa, Op, op, expected)                       \
     158             :   (csa)->Assert(                                                           \
     159             :       [&]() -> compiler::Node* {                                           \
     160             :         compiler::Node* const argc =                                       \
     161             :             (csa)->Parameter(Descriptor::kJSActualArgumentsCount);         \
     162             :         return (csa)->Op(argc, (csa)->Int32Constant(expected));            \
     163             :       },                                                                   \
     164             :       "argc " #op " " #expected, __FILE__, __LINE__,                       \
     165             :       SmiFromInt32((csa)->Parameter(Descriptor::kJSActualArgumentsCount)), \
     166             :       "argc")
     167             : 
     168             : #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) \
     169             :   CSA_ASSERT_JS_ARGC_OP(csa, Word32Equal, ==, expected)
     170             : 
     171             : #define CSA_DEBUG_INFO(name) \
     172             :   { #name, __FILE__, __LINE__ }
     173             : #define BIND(label) Bind(label, CSA_DEBUG_INFO(label))
     174             : #define VARIABLE(name, ...) \
     175             :   Variable name(this, CSA_DEBUG_INFO(name), __VA_ARGS__)
     176             : #define VARIABLE_CONSTRUCTOR(name, ...) \
     177             :   name(this, CSA_DEBUG_INFO(name), __VA_ARGS__)
     178             : #define TYPED_VARIABLE_DEF(type, name, ...) \
     179             :   TVariable<type> name(CSA_DEBUG_INFO(name), __VA_ARGS__)
     180             : #else  // DEBUG
     181             : #define CSA_ASSERT(csa, ...) ((void)0)
     182             : #define CSA_ASSERT_BRANCH(csa, ...) ((void)0)
     183             : #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) ((void)0)
     184             : #define BIND(label) Bind(label)
     185             : #define VARIABLE(name, ...) Variable name(this, __VA_ARGS__)
     186             : #define VARIABLE_CONSTRUCTOR(name, ...) name(this, __VA_ARGS__)
     187             : #define TYPED_VARIABLE_DEF(type, name, ...) TVariable<type> name(__VA_ARGS__)
     188             : #endif  // DEBUG
     189             : 
     190             : #define TVARIABLE(...) EXPAND(TYPED_VARIABLE_DEF(__VA_ARGS__, this))
     191             : 
     192             : #ifdef ENABLE_SLOW_DCHECKS
     193             : #define CSA_SLOW_ASSERT(csa, ...) \
     194             :   if (FLAG_enable_slow_asserts) { \
     195             :     CSA_ASSERT(csa, __VA_ARGS__); \
     196             :   }
     197             : #else
     198             : #define CSA_SLOW_ASSERT(csa, ...) ((void)0)
     199             : #endif
     200             : 
     201             : // Provides JavaScript-specific "macro-assembler" functionality on top of the
     202             : // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
     203             : // it's possible to add JavaScript-specific useful CodeAssembler "macros"
     204             : // without modifying files in the compiler directory (and requiring a review
     205             : // from a compiler directory OWNER).
     206      532433 : class V8_EXPORT_PRIVATE CodeStubAssembler
     207             :     : public compiler::CodeAssembler,
     208             :       public BaseBuiltinsFromDSLAssembler {
     209             :  public:
     210             :   using Node = compiler::Node;
     211             :   template <class T>
     212             :   using TNode = compiler::TNode<T>;
     213             :   template <class T>
     214             :   using SloppyTNode = compiler::SloppyTNode<T>;
     215             : 
     216             :   template <typename T>
     217             :   using LazyNode = std::function<TNode<T>()>;
     218             : 
     219             :   explicit CodeStubAssembler(compiler::CodeAssemblerState* state);
     220             : 
     221             :   enum AllocationFlag : uint8_t {
     222             :     kNone = 0,
     223             :     kDoubleAlignment = 1,
     224             :     kPretenured = 1 << 1,
     225             :     kAllowLargeObjectAllocation = 1 << 2,
     226             :   };
     227             : 
     228             :   enum SlackTrackingMode { kWithSlackTracking, kNoSlackTracking };
     229             : 
     230             :   typedef base::Flags<AllocationFlag> AllocationFlags;
     231             : 
     232             :   enum ParameterMode { SMI_PARAMETERS, INTPTR_PARAMETERS };
     233             : 
     234             :   // On 32-bit platforms, there is a slight performance advantage to doing all
     235             :   // of the array offset/index arithmetic with SMIs, since it's possible
     236             :   // to save a few tag/untag operations without paying an extra expense when
     237             :   // calculating array offset (the smi math can be folded away) and there are
     238             :   // fewer live ranges. Thus only convert indices to untagged value on 64-bit
     239             :   // platforms.
     240        2592 :   ParameterMode OptimalParameterMode() const {
     241        2604 :     return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS;
     242             :   }
     243             : 
     244        1044 :   MachineRepresentation ParameterRepresentation(ParameterMode mode) const {
     245             :     return mode == INTPTR_PARAMETERS ? MachineType::PointerRepresentation()
     246        1044 :                                      : MachineRepresentation::kTaggedSigned;
     247             :   }
     248             : 
     249         596 :   MachineRepresentation OptimalParameterRepresentation() const {
     250         596 :     return ParameterRepresentation(OptimalParameterMode());
     251             :   }
     252             : 
     253       21040 :   TNode<IntPtrT> ParameterToIntPtr(Node* value, ParameterMode mode) {
     254       21040 :     if (mode == SMI_PARAMETERS) value = SmiUntag(value);
     255       21040 :     return UncheckedCast<IntPtrT>(value);
     256             :   }
     257             : 
     258        8324 :   Node* IntPtrToParameter(SloppyTNode<IntPtrT> value, ParameterMode mode) {
     259        8324 :     if (mode == SMI_PARAMETERS) return SmiTag(value);
     260        8324 :     return value;
     261             :   }
     262             : 
     263             :   Node* Int32ToParameter(SloppyTNode<Int32T> value, ParameterMode mode) {
     264             :     return IntPtrToParameter(ChangeInt32ToIntPtr(value), mode);
     265             :   }
     266             : 
     267       22140 :   TNode<Smi> ParameterToTagged(Node* value, ParameterMode mode) {
     268       22140 :     if (mode != SMI_PARAMETERS) return SmiTag(value);
     269        3664 :     return UncheckedCast<Smi>(value);
     270             :   }
     271             : 
     272       11624 :   Node* TaggedToParameter(SloppyTNode<Smi> value, ParameterMode mode) {
     273       11624 :     if (mode != SMI_PARAMETERS) return SmiUntag(value);
     274           4 :     return value;
     275             :   }
     276             : 
     277       11820 :   bool ToParameterConstant(Node* node, intptr_t* out, ParameterMode mode) {
     278       11820 :     if (mode == ParameterMode::SMI_PARAMETERS) {
     279         752 :       Smi constant;
     280         752 :       if (ToSmiConstant(node, &constant)) {
     281           8 :         *out = static_cast<intptr_t>(constant->value());
     282           8 :         return true;
     283             :       }
     284             :     } else {
     285             :       DCHECK_EQ(mode, ParameterMode::INTPTR_PARAMETERS);
     286             :       intptr_t constant;
     287       11068 :       if (ToIntPtrConstant(node, constant)) {
     288         640 :         *out = constant;
     289         640 :         return true;
     290             :       }
     291             :     }
     292             : 
     293       11172 :     return false;
     294             :   }
     295             : 
     296             : #if defined(V8_HOST_ARCH_32_BIT)
     297             :   TNode<Smi> BIntToSmi(TNode<BInt> source) { return source; }
     298             :   TNode<IntPtrT> BIntToIntPtr(TNode<BInt> source) {
     299             :     return SmiToIntPtr(source);
     300             :   }
     301             :   TNode<BInt> SmiToBInt(TNode<Smi> source) { return source; }
     302             :   TNode<BInt> IntPtrToBInt(TNode<IntPtrT> source) {
     303             :     return SmiFromIntPtr(source);
     304             :   }
     305             : #elif defined(V8_HOST_ARCH_64_BIT)
     306             :   TNode<Smi> BIntToSmi(TNode<BInt> source) { return SmiFromIntPtr(source); }
     307             :   TNode<IntPtrT> BIntToIntPtr(TNode<BInt> source) { return source; }
     308         168 :   TNode<BInt> SmiToBInt(TNode<Smi> source) { return SmiToIntPtr(source); }
     309         168 :   TNode<BInt> IntPtrToBInt(TNode<IntPtrT> source) { return source; }
     310             : #else
     311             : #error Unknown architecture.
     312             : #endif
     313             : 
     314        1904 :   TNode<Smi> TaggedToSmi(TNode<Object> value, Label* fail) {
     315        1904 :     GotoIf(TaggedIsNotSmi(value), fail);
     316        1904 :     return UncheckedCast<Smi>(value);
     317             :   }
     318             : 
     319          56 :   TNode<Smi> TaggedToPositiveSmi(TNode<Object> value, Label* fail) {
     320          56 :     GotoIfNot(TaggedIsPositiveSmi(value), fail);
     321          56 :     return UncheckedCast<Smi>(value);
     322             :   }
     323             : 
     324             :   TNode<String> TaggedToDirectString(TNode<Object> value, Label* fail);
     325             : 
     326        2744 :   TNode<Number> TaggedToNumber(TNode<Object> value, Label* fail) {
     327        2744 :     GotoIfNot(IsNumber(value), fail);
     328        2744 :     return UncheckedCast<Number>(value);
     329             :   }
     330             : 
     331       10248 :   TNode<HeapObject> TaggedToHeapObject(TNode<Object> value, Label* fail) {
     332       10248 :     GotoIf(TaggedIsSmi(value), fail);
     333       10248 :     return UncheckedCast<HeapObject>(value);
     334             :   }
     335             : 
     336        1232 :   TNode<JSArray> HeapObjectToJSArray(TNode<HeapObject> heap_object,
     337             :                                      Label* fail) {
     338        1232 :     GotoIfNot(IsJSArray(heap_object), fail);
     339        1232 :     return UncheckedCast<JSArray>(heap_object);
     340             :   }
     341             : 
     342         168 :   TNode<JSArrayBuffer> HeapObjectToJSArrayBuffer(TNode<HeapObject> heap_object,
     343             :                                                  Label* fail) {
     344         168 :     GotoIfNot(IsJSArrayBuffer(heap_object), fail);
     345         168 :     return UncheckedCast<JSArrayBuffer>(heap_object);
     346             :   }
     347             : 
     348             :   TNode<JSArray> TaggedToFastJSArray(TNode<Context> context,
     349             :                                      TNode<Object> value, Label* fail) {
     350             :     GotoIf(TaggedIsSmi(value), fail);
     351             :     TNode<HeapObject> heap_object = CAST(value);
     352             :     GotoIfNot(IsFastJSArray(heap_object, context), fail);
     353             :     return UncheckedCast<JSArray>(heap_object);
     354             :   }
     355             : 
     356        1288 :   TNode<JSDataView> HeapObjectToJSDataView(TNode<HeapObject> heap_object,
     357             :                                            Label* fail) {
     358        1288 :     GotoIfNot(IsJSDataView(heap_object), fail);
     359        1288 :     return CAST(heap_object);
     360             :   }
     361             : 
     362           0 :   TNode<JSProxy> HeapObjectToJSProxy(TNode<HeapObject> heap_object,
     363             :                                      Label* fail) {
     364           0 :     GotoIfNot(IsJSProxy(heap_object), fail);
     365           0 :     return CAST(heap_object);
     366             :   }
     367             : 
     368        2352 :   TNode<JSReceiver> HeapObjectToCallable(TNode<HeapObject> heap_object,
     369             :                                          Label* fail) {
     370        2352 :     GotoIfNot(IsCallable(heap_object), fail);
     371        2352 :     return CAST(heap_object);
     372             :   }
     373             : 
     374         336 :   TNode<String> HeapObjectToString(TNode<HeapObject> heap_object, Label* fail) {
     375         336 :     GotoIfNot(IsString(heap_object), fail);
     376         336 :     return CAST(heap_object);
     377             :   }
     378             : 
     379         280 :   TNode<JSReceiver> HeapObjectToConstructor(TNode<HeapObject> heap_object,
     380             :                                             Label* fail) {
     381         280 :     GotoIfNot(IsConstructor(heap_object), fail);
     382         280 :     return CAST(heap_object);
     383             :   }
     384             : 
     385             :   Node* MatchesParameterMode(Node* value, ParameterMode mode);
     386             : 
     387             : #define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \
     388             :   Node* OpName(Node* a, Node* b, ParameterMode mode) {   \
     389             :     if (mode == SMI_PARAMETERS) {                        \
     390             :       return SmiOpName(CAST(a), CAST(b));                \
     391             :     } else {                                             \
     392             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);                \
     393             :       return IntPtrOpName(a, b);                         \
     394             :     }                                                    \
     395             :   }
     396          56 :   PARAMETER_BINOP(IntPtrOrSmiMin, IntPtrMin, SmiMin)
     397       72188 :   PARAMETER_BINOP(IntPtrOrSmiAdd, IntPtrAdd, SmiAdd)
     398       12896 :   PARAMETER_BINOP(IntPtrOrSmiSub, IntPtrSub, SmiSub)
     399             :   PARAMETER_BINOP(IntPtrOrSmiLessThan, IntPtrLessThan, SmiLessThan)
     400          56 :   PARAMETER_BINOP(IntPtrOrSmiLessThanOrEqual, IntPtrLessThanOrEqual,
     401             :                   SmiLessThanOrEqual)
     402       11936 :   PARAMETER_BINOP(IntPtrOrSmiGreaterThan, IntPtrGreaterThan, SmiGreaterThan)
     403             :   PARAMETER_BINOP(IntPtrOrSmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual,
     404             :                   SmiGreaterThanOrEqual)
     405             :   PARAMETER_BINOP(UintPtrOrSmiLessThan, UintPtrLessThan, SmiBelow)
     406       17116 :   PARAMETER_BINOP(UintPtrOrSmiGreaterThanOrEqual, UintPtrGreaterThanOrEqual,
     407             :                   SmiAboveOrEqual)
     408             : #undef PARAMETER_BINOP
     409             : 
     410         168 :   uintptr_t ConstexprUintPtrShl(uintptr_t a, int32_t b) { return a << b; }
     411             :   uintptr_t ConstexprUintPtrShr(uintptr_t a, int32_t b) { return a >> b; }
     412         112 :   intptr_t ConstexprIntPtrAdd(intptr_t a, intptr_t b) { return a + b; }
     413             :   uintptr_t ConstexprUintPtrAdd(uintptr_t a, uintptr_t b) { return a + b; }
     414         112 :   intptr_t ConstexprWordNot(intptr_t a) { return ~a; }
     415             :   uintptr_t ConstexprWordNot(uintptr_t a) { return ~a; }
     416             : 
     417             :   TNode<Object> NoContextConstant();
     418             : 
     419             : #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name)  \
     420             :   compiler::TNode<std::remove_pointer<std::remove_reference<decltype(  \
     421             :       std::declval<ReadOnlyRoots>().rootAccessorName())>::type>::type> \
     422             :       name##Constant();
     423             :   HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR)
     424             : #undef HEAP_CONSTANT_ACCESSOR
     425             : 
     426             : #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name) \
     427             :   compiler::TNode<std::remove_pointer<std::remove_reference<decltype( \
     428             :       std::declval<Heap>().rootAccessorName())>::type>::type>         \
     429             :       name##Constant();
     430             :   HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR)
     431             : #undef HEAP_CONSTANT_ACCESSOR
     432             : 
     433             : #define HEAP_CONSTANT_TEST(rootIndexName, rootAccessorName, name) \
     434             :   TNode<BoolT> Is##name(SloppyTNode<Object> value);               \
     435             :   TNode<BoolT> IsNot##name(SloppyTNode<Object> value);
     436             :   HEAP_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_TEST)
     437             : #undef HEAP_CONSTANT_TEST
     438             : 
     439             :   Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
     440             : 
     441             :   bool IsIntPtrOrSmiConstantZero(Node* test, ParameterMode mode);
     442             :   bool TryGetIntPtrOrSmiConstantValue(Node* maybe_constant, int* value,
     443             :                                       ParameterMode mode);
     444             : 
     445             :   // Round the 32bits payload of the provided word up to the next power of two.
     446             :   TNode<IntPtrT> IntPtrRoundUpToPowerOfTwo32(TNode<IntPtrT> value);
     447             :   // Select the maximum of the two provided IntPtr values.
     448             :   TNode<IntPtrT> IntPtrMax(SloppyTNode<IntPtrT> left,
     449             :                            SloppyTNode<IntPtrT> right);
     450             :   // Select the minimum of the two provided IntPtr values.
     451             :   TNode<IntPtrT> IntPtrMin(SloppyTNode<IntPtrT> left,
     452             :                            SloppyTNode<IntPtrT> right);
     453             : 
     454             :   // Float64 operations.
     455             :   TNode<Float64T> Float64Ceil(SloppyTNode<Float64T> x);
     456             :   TNode<Float64T> Float64Floor(SloppyTNode<Float64T> x);
     457             :   TNode<Float64T> Float64Round(SloppyTNode<Float64T> x);
     458             :   TNode<Float64T> Float64RoundToEven(SloppyTNode<Float64T> x);
     459             :   TNode<Float64T> Float64Trunc(SloppyTNode<Float64T> x);
     460             :   // Select the minimum of the two provided Number values.
     461             :   TNode<Number> NumberMax(SloppyTNode<Number> left, SloppyTNode<Number> right);
     462             :   // Select the minimum of the two provided Number values.
     463             :   TNode<Number> NumberMin(SloppyTNode<Number> left, SloppyTNode<Number> right);
     464             : 
     465             :   // After converting an index to an integer, calculate a relative index: if
     466             :   // index < 0, max(length + index, 0); else min(index, length)
     467             :   TNode<IntPtrT> ConvertToRelativeIndex(TNode<Context> context,
     468             :                                         TNode<Object> index,
     469             :                                         TNode<IntPtrT> length);
     470             : 
     471             :   // Returns true iff the given value fits into smi range and is >= 0.
     472             :   TNode<BoolT> IsValidPositiveSmi(TNode<IntPtrT> value);
     473             : 
     474             :   // Tag an IntPtr as a Smi value.
     475             :   TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value);
     476             :   // Untag a Smi value as an IntPtr.
     477             :   TNode<IntPtrT> SmiUntag(SloppyTNode<Smi> value);
     478             : 
     479             :   // Smi conversions.
     480             :   TNode<Float64T> SmiToFloat64(SloppyTNode<Smi> value);
     481        7792 :   TNode<Smi> SmiFromIntPtr(SloppyTNode<IntPtrT> value) { return SmiTag(value); }
     482             :   TNode<Smi> SmiFromInt32(SloppyTNode<Int32T> value);
     483       78292 :   TNode<IntPtrT> SmiToIntPtr(SloppyTNode<Smi> value) { return SmiUntag(value); }
     484             :   TNode<Int32T> SmiToInt32(SloppyTNode<Smi> value);
     485             : 
     486             :   // Smi operations.
     487             : #define SMI_ARITHMETIC_BINOP(SmiOpName, IntPtrOpName, Int32OpName)       \
     488             :   TNode<Smi> SmiOpName(TNode<Smi> a, TNode<Smi> b) {                     \
     489             :     if (SmiValuesAre32Bits()) {                                          \
     490             :       return BitcastWordToTaggedSigned(                                  \
     491             :           IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); \
     492             :     } else {                                                             \
     493             :       DCHECK(SmiValuesAre31Bits());                                      \
     494             :       if (kSystemPointerSize == kInt64Size) {                            \
     495             :         CSA_ASSERT(this, IsValidSmi(a));                                 \
     496             :         CSA_ASSERT(this, IsValidSmi(b));                                 \
     497             :       }                                                                  \
     498             :       return BitcastWordToTaggedSigned(ChangeInt32ToIntPtr(              \
     499             :           Int32OpName(TruncateIntPtrToInt32(BitcastTaggedToWord(a)),     \
     500             :                       TruncateIntPtrToInt32(BitcastTaggedToWord(b)))));  \
     501             :     }                                                                    \
     502             :   }
     503       16732 :   SMI_ARITHMETIC_BINOP(SmiAdd, IntPtrAdd, Int32Add)
     504        8216 :   SMI_ARITHMETIC_BINOP(SmiSub, IntPtrSub, Int32Sub)
     505        1120 :   SMI_ARITHMETIC_BINOP(SmiAnd, WordAnd, Word32And)
     506       35672 :   SMI_ARITHMETIC_BINOP(SmiOr, WordOr, Word32Or)
     507             : #undef SMI_ARITHMETIC_BINOP
     508          56 :   TNode<Smi> SmiInc(TNode<Smi> value) { return SmiAdd(value, SmiConstant(1)); }
     509             : 
     510             :   TNode<IntPtrT> TryIntPtrAdd(TNode<IntPtrT> a, TNode<IntPtrT> b,
     511             :                               Label* if_overflow);
     512             :   TNode<Smi> TrySmiAdd(TNode<Smi> a, TNode<Smi> b, Label* if_overflow);
     513             :   TNode<Smi> TrySmiSub(TNode<Smi> a, TNode<Smi> b, Label* if_overflow);
     514             : 
     515        4088 :   TNode<Smi> SmiShl(TNode<Smi> a, int shift) {
     516        4088 :     return BitcastWordToTaggedSigned(WordShl(BitcastTaggedToWord(a), shift));
     517             :   }
     518             : 
     519        3140 :   TNode<Smi> SmiShr(TNode<Smi> a, int shift) {
     520             :     return BitcastWordToTaggedSigned(
     521        6280 :         WordAnd(WordShr(BitcastTaggedToWord(a), shift),
     522        9420 :                 BitcastTaggedToWord(SmiConstant(-1))));
     523             :   }
     524             : 
     525         280 :   TNode<Smi> SmiSar(TNode<Smi> a, int shift) {
     526             :     return BitcastWordToTaggedSigned(
     527         560 :         WordAnd(WordSar(BitcastTaggedToWord(a), shift),
     528         840 :                 BitcastTaggedToWord(SmiConstant(-1))));
     529             :   }
     530             : 
     531             :   Node* WordOrSmiShl(Node* a, int shift, ParameterMode mode) {
     532             :     if (mode == SMI_PARAMETERS) {
     533             :       return SmiShl(CAST(a), shift);
     534             :     } else {
     535             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);
     536             :       return WordShl(a, shift);
     537             :     }
     538             :   }
     539             : 
     540        2564 :   Node* WordOrSmiShr(Node* a, int shift, ParameterMode mode) {
     541        2564 :     if (mode == SMI_PARAMETERS) {
     542         116 :       return SmiShr(CAST(a), shift);
     543             :     } else {
     544             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);
     545        2448 :       return WordShr(a, shift);
     546             :     }
     547             :   }
     548             : 
     549             : #define SMI_COMPARISON_OP(SmiOpName, IntPtrOpName, Int32OpName)            \
     550             :   TNode<BoolT> SmiOpName(TNode<Smi> a, TNode<Smi> b) {                     \
     551             :     if (SmiValuesAre32Bits()) {                                            \
     552             :       return IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b)); \
     553             :     } else {                                                               \
     554             :       DCHECK(SmiValuesAre31Bits());                                        \
     555             :       if (kSystemPointerSize == kInt64Size) {                              \
     556             :         CSA_ASSERT(this, IsValidSmi(a));                                   \
     557             :         CSA_ASSERT(this, IsValidSmi(b));                                   \
     558             :       }                                                                    \
     559             :       return Int32OpName(TruncateIntPtrToInt32(BitcastTaggedToWord(a)),    \
     560             :                          TruncateIntPtrToInt32(BitcastTaggedToWord(b)));   \
     561             :     }                                                                      \
     562             :   }
     563       24808 :   SMI_COMPARISON_OP(SmiEqual, WordEqual, Word32Equal)
     564         616 :   SMI_COMPARISON_OP(SmiNotEqual, WordNotEqual, Word32NotEqual)
     565        2912 :   SMI_COMPARISON_OP(SmiAbove, UintPtrGreaterThan, Uint32GreaterThan)
     566         224 :   SMI_COMPARISON_OP(SmiAboveOrEqual, UintPtrGreaterThanOrEqual,
     567             :                     Uint32GreaterThanOrEqual)
     568        9748 :   SMI_COMPARISON_OP(SmiBelow, UintPtrLessThan, Uint32LessThan)
     569       13160 :   SMI_COMPARISON_OP(SmiLessThan, IntPtrLessThan, Int32LessThan)
     570        5004 :   SMI_COMPARISON_OP(SmiLessThanOrEqual, IntPtrLessThanOrEqual,
     571             :                     Int32LessThanOrEqual)
     572        5336 :   SMI_COMPARISON_OP(SmiGreaterThan, IntPtrGreaterThan, Int32GreaterThan)
     573        2408 :   SMI_COMPARISON_OP(SmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual,
     574             :                     Int32GreaterThanOrEqual)
     575             : #undef SMI_COMPARISON_OP
     576             :   TNode<Smi> SmiMax(TNode<Smi> a, TNode<Smi> b);
     577             :   TNode<Smi> SmiMin(TNode<Smi> a, TNode<Smi> b);
     578             :   // Computes a % b for Smi inputs a and b; result is not necessarily a Smi.
     579             :   TNode<Number> SmiMod(TNode<Smi> a, TNode<Smi> b);
     580             :   // Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
     581             :   TNode<Number> SmiMul(TNode<Smi> a, TNode<Smi> b);
     582             :   // Tries to compute dividend / divisor for Smi inputs; branching to bailout
     583             :   // if the division needs to be performed as a floating point operation.
     584             :   TNode<Smi> TrySmiDiv(TNode<Smi> dividend, TNode<Smi> divisor, Label* bailout);
     585             : 
     586             :   // Compares two Smis a and b as if they were converted to strings and then
     587             :   // compared lexicographically. Returns:
     588             :   // -1 iff x < y.
     589             :   //  0 iff x == y.
     590             :   //  1 iff x > y.
     591             :   TNode<Smi> SmiLexicographicCompare(TNode<Smi> x, TNode<Smi> y);
     592             : 
     593             :   // Smi | HeapNumber operations.
     594             :   TNode<Number> NumberInc(SloppyTNode<Number> value);
     595             :   TNode<Number> NumberDec(SloppyTNode<Number> value);
     596             :   TNode<Number> NumberAdd(SloppyTNode<Number> a, SloppyTNode<Number> b);
     597             :   TNode<Number> NumberSub(SloppyTNode<Number> a, SloppyTNode<Number> b);
     598             :   void GotoIfNotNumber(Node* value, Label* is_not_number);
     599             :   void GotoIfNumber(Node* value, Label* is_number);
     600             :   TNode<Number> SmiToNumber(TNode<Smi> v) { return v; }
     601             : 
     602             :   TNode<Number> BitwiseOp(Node* left32, Node* right32, Operation bitwise_op);
     603             : 
     604             :   // Allocate an object of the given size.
     605             :   TNode<HeapObject> AllocateInNewSpace(TNode<IntPtrT> size,
     606             :                                        AllocationFlags flags = kNone);
     607             :   TNode<HeapObject> AllocateInNewSpace(int size, AllocationFlags flags = kNone);
     608             :   TNode<HeapObject> Allocate(TNode<IntPtrT> size,
     609             :                              AllocationFlags flags = kNone);
     610             :   TNode<HeapObject> Allocate(int size, AllocationFlags flags = kNone);
     611             :   TNode<HeapObject> InnerAllocate(TNode<HeapObject> previous, int offset);
     612             :   TNode<HeapObject> InnerAllocate(TNode<HeapObject> previous,
     613             :                                   TNode<IntPtrT> offset);
     614             : 
     615             :   TNode<BoolT> IsRegularHeapObjectSize(TNode<IntPtrT> size);
     616             : 
     617             :   typedef std::function<void(Label*, Label*)> BranchGenerator;
     618             :   typedef std::function<Node*()> NodeGenerator;
     619             : 
     620             :   void Assert(const BranchGenerator& branch, const char* message = nullptr,
     621             :               const char* file = nullptr, int line = 0,
     622             :               Node* extra_node1 = nullptr, const char* extra_node1_name = "",
     623             :               Node* extra_node2 = nullptr, const char* extra_node2_name = "",
     624             :               Node* extra_node3 = nullptr, const char* extra_node3_name = "",
     625             :               Node* extra_node4 = nullptr, const char* extra_node4_name = "",
     626             :               Node* extra_node5 = nullptr, const char* extra_node5_name = "");
     627             :   void Assert(const NodeGenerator& condition_body,
     628             :               const char* message = nullptr, const char* file = nullptr,
     629             :               int line = 0, Node* extra_node1 = nullptr,
     630             :               const char* extra_node1_name = "", Node* extra_node2 = nullptr,
     631             :               const char* extra_node2_name = "", Node* extra_node3 = nullptr,
     632             :               const char* extra_node3_name = "", Node* extra_node4 = nullptr,
     633             :               const char* extra_node4_name = "", Node* extra_node5 = nullptr,
     634             :               const char* extra_node5_name = "");
     635             :   void Check(const BranchGenerator& branch, const char* message = nullptr,
     636             :              const char* file = nullptr, int line = 0,
     637             :              Node* extra_node1 = nullptr, const char* extra_node1_name = "",
     638             :              Node* extra_node2 = nullptr, const char* extra_node2_name = "",
     639             :              Node* extra_node3 = nullptr, const char* extra_node3_name = "",
     640             :              Node* extra_node4 = nullptr, const char* extra_node4_name = "",
     641             :              Node* extra_node5 = nullptr, const char* extra_node5_name = "");
     642             :   void Check(const NodeGenerator& condition_body, const char* message = nullptr,
     643             :              const char* file = nullptr, int line = 0,
     644             :              Node* extra_node1 = nullptr, const char* extra_node1_name = "",
     645             :              Node* extra_node2 = nullptr, const char* extra_node2_name = "",
     646             :              Node* extra_node3 = nullptr, const char* extra_node3_name = "",
     647             :              Node* extra_node4 = nullptr, const char* extra_node4_name = "",
     648             :              Node* extra_node5 = nullptr, const char* extra_node5_name = "");
     649             :   void FailAssert(
     650             :       const char* message = nullptr, const char* file = nullptr, int line = 0,
     651             :       Node* extra_node1 = nullptr, const char* extra_node1_name = "",
     652             :       Node* extra_node2 = nullptr, const char* extra_node2_name = "",
     653             :       Node* extra_node3 = nullptr, const char* extra_node3_name = "",
     654             :       Node* extra_node4 = nullptr, const char* extra_node4_name = "",
     655             :       Node* extra_node5 = nullptr, const char* extra_node5_name = "");
     656             : 
     657             :   void FastCheck(TNode<BoolT> condition);
     658             : 
     659             :   // The following Call wrappers call an object according to the semantics that
     660             :   // one finds in the EcmaScript spec, operating on an Callable (e.g. a
     661             :   // JSFunction or proxy) rather than a Code object.
     662             :   template <class... TArgs>
     663             :   TNode<Object> Call(TNode<Context> context, TNode<Object> callable,
     664             :                      TNode<JSReceiver> receiver, TArgs... args) {
     665             :     return UncheckedCast<Object>(CallJS(
     666             :         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
     667             :         context, callable, receiver, args...));
     668             :   }
     669             :   template <class... TArgs>
     670        1848 :   TNode<Object> Call(TNode<Context> context, TNode<Object> callable,
     671             :                      TNode<Object> receiver, TArgs... args) {
     672        1848 :     if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) {
     673             :       return UncheckedCast<Object>(CallJS(
     674             :           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
     675         280 :           context, callable, receiver, args...));
     676             :     }
     677             :     return UncheckedCast<Object>(CallJS(CodeFactory::Call(isolate()), context,
     678        1568 :                                         callable, receiver, args...));
     679             :   }
     680             : 
     681             :   template <class... TArgs>
     682        1064 :   TNode<JSReceiver> ConstructWithTarget(TNode<Context> context,
     683             :                                         TNode<JSReceiver> target,
     684             :                                         TNode<JSReceiver> new_target,
     685             :                                         TArgs... args) {
     686        1624 :     return CAST(ConstructJSWithTarget(CodeFactory::Construct(isolate()),
     687             :                                       context, target, new_target,
     688             :                                       implicit_cast<TNode<Object>>(args)...));
     689             :   }
     690             :   template <class... TArgs>
     691         952 :   TNode<JSReceiver> Construct(TNode<Context> context,
     692             :                               TNode<JSReceiver> new_target, TArgs... args) {
     693         952 :     return ConstructWithTarget(context, new_target, new_target, args...);
     694             :   }
     695             : 
     696             :   template <class A, class F, class G>
     697       41884 :   TNode<A> Select(SloppyTNode<BoolT> condition, const F& true_body,
     698             :                   const G& false_body) {
     699       83768 :     return UncheckedCast<A>(SelectImpl(
     700             :         condition,
     701       83768 :         [&]() -> Node* { return implicit_cast<TNode<A>>(true_body()); },
     702       83768 :         [&]() -> Node* { return implicit_cast<TNode<A>>(false_body()); },
     703       83768 :         MachineRepresentationOf<A>::value));
     704             :   }
     705             : 
     706             :   template <class A>
     707       12496 :   TNode<A> SelectConstant(TNode<BoolT> condition, TNode<A> true_value,
     708             :                           TNode<A> false_value) {
     709       37488 :     return Select<A>(condition, [=] { return true_value; },
     710       37488 :                      [=] { return false_value; });
     711             :   }
     712             : 
     713             :   TNode<Int32T> SelectInt32Constant(SloppyTNode<BoolT> condition,
     714             :                                     int true_value, int false_value);
     715             :   TNode<IntPtrT> SelectIntPtrConstant(SloppyTNode<BoolT> condition,
     716             :                                       int true_value, int false_value);
     717             :   TNode<Oddball> SelectBooleanConstant(SloppyTNode<BoolT> condition);
     718             :   TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, Smi true_value,
     719             :                                Smi false_value);
     720             :   TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, int true_value,
     721             :                                Smi false_value) {
     722             :     return SelectSmiConstant(condition, Smi::FromInt(true_value), false_value);
     723             :   }
     724             :   TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, Smi true_value,
     725             :                                int false_value) {
     726             :     return SelectSmiConstant(condition, true_value, Smi::FromInt(false_value));
     727             :   }
     728        4144 :   TNode<Smi> SelectSmiConstant(SloppyTNode<BoolT> condition, int true_value,
     729             :                                int false_value) {
     730             :     return SelectSmiConstant(condition, Smi::FromInt(true_value),
     731        4144 :                              Smi::FromInt(false_value));
     732             :   }
     733             : 
     734             :   TNode<Int32T> TruncateIntPtrToInt32(SloppyTNode<IntPtrT> value);
     735             : 
     736             :   // Check a value for smi-ness
     737             :   TNode<BoolT> TaggedIsSmi(SloppyTNode<Object> a);
     738             :   TNode<BoolT> TaggedIsSmi(TNode<MaybeObject> a);
     739             :   TNode<BoolT> TaggedIsNotSmi(SloppyTNode<Object> a);
     740             :   // Check that the value is a non-negative smi.
     741             :   TNode<BoolT> TaggedIsPositiveSmi(SloppyTNode<Object> a);
     742             :   // Check that a word has a word-aligned address.
     743             :   TNode<BoolT> WordIsAligned(SloppyTNode<WordT> word, size_t alignment);
     744             :   TNode<BoolT> WordIsPowerOfTwo(SloppyTNode<IntPtrT> value);
     745             : 
     746             : #if DEBUG
     747             :   void Bind(Label* label, AssemblerDebugInfo debug_info);
     748             : #endif  // DEBUG
     749             :   void Bind(Label* label);
     750             : 
     751             :   template <class... T>
     752             :   void Bind(compiler::CodeAssemblerParameterizedLabel<T...>* label,
     753             :             TNode<T>*... phis) {
     754             :     CodeAssembler::Bind(label, phis...);
     755             :   }
     756             : 
     757        5376 :   void BranchIfSmiEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true,
     758             :                         Label* if_false) {
     759        5376 :     Branch(SmiEqual(a, b), if_true, if_false);
     760        5376 :   }
     761             : 
     762        5544 :   void BranchIfSmiLessThan(TNode<Smi> a, TNode<Smi> b, Label* if_true,
     763             :                            Label* if_false) {
     764        5544 :     Branch(SmiLessThan(a, b), if_true, if_false);
     765        5544 :   }
     766             : 
     767        3828 :   void BranchIfSmiLessThanOrEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true,
     768             :                                   Label* if_false) {
     769        3828 :     Branch(SmiLessThanOrEqual(a, b), if_true, if_false);
     770        3828 :   }
     771             : 
     772        1680 :   void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
     773        1680 :     Branch(Float64Equal(value, value), if_false, if_true);
     774        1680 :   }
     775             : 
     776             :   // Branches to {if_true} if ToBoolean applied to {value} yields true,
     777             :   // otherwise goes to {if_false}.
     778             :   void BranchIfToBooleanIsTrue(Node* value, Label* if_true, Label* if_false);
     779             : 
     780             :   void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false);
     781             : 
     782             :   // Branches to {if_true} when --force-slow-path flag has been passed.
     783             :   // It's used for testing to ensure that slow path implementation behave
     784             :   // equivalent to corresponding fast paths (where applicable).
     785             :   //
     786             :   // Works only with V8_ENABLE_FORCE_SLOW_PATH compile time flag. Nop otherwise.
     787             :   void GotoIfForceSlowPath(Label* if_true);
     788             : 
     789             :   // Branches to {if_true} when Debug::ExecutionMode is DebugInfo::kSideEffect.
     790             :   void GotoIfDebugExecutionModeChecksSideEffects(Label* if_true);
     791             : 
     792             :   // Load value from current parent frame by given offset in bytes.
     793             :   Node* LoadFromParentFrame(int offset,
     794             :                             MachineType rep = MachineType::AnyTagged());
     795             : 
     796             :   // Load an object pointer from a buffer that isn't in the heap.
     797             :   Node* LoadBufferObject(Node* buffer, int offset,
     798             :                          MachineType rep = MachineType::AnyTagged());
     799         168 :   TNode<RawPtrT> LoadBufferPointer(TNode<RawPtrT> buffer, int offset) {
     800             :     return UncheckedCast<RawPtrT>(
     801         168 :         LoadBufferObject(buffer, offset, MachineType::Pointer()));
     802             :   }
     803         168 :   TNode<Smi> LoadBufferSmi(TNode<RawPtrT> buffer, int offset) {
     804         168 :     return CAST(LoadBufferObject(buffer, offset, MachineType::TaggedSigned()));
     805             :   }
     806             :   // Load a field from an object on the heap.
     807             :   Node* LoadObjectField(SloppyTNode<HeapObject> object, int offset,
     808             :                         MachineType rep);
     809             :   template <class T, typename std::enable_if<
     810             :                          std::is_convertible<TNode<T>, TNode<Object>>::value,
     811             :                          int>::type = 0>
     812        9860 :   TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) {
     813        9860 :     return CAST(LoadObjectField(object, offset, MachineTypeOf<T>::value));
     814             :   }
     815             :   template <class T, typename std::enable_if<
     816             :                          std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
     817             :                          int>::type = 0>
     818       49500 :   TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) {
     819       99000 :     return UncheckedCast<T>(
     820       99000 :         LoadObjectField(object, offset, MachineTypeOf<T>::value));
     821             :   }
     822      244600 :   TNode<Object> LoadObjectField(SloppyTNode<HeapObject> object, int offset) {
     823             :     return UncheckedCast<Object>(
     824      244780 :         LoadObjectField(object, offset, MachineType::AnyTagged()));
     825             :   }
     826             :   Node* LoadObjectField(SloppyTNode<HeapObject> object,
     827             :                         SloppyTNode<IntPtrT> offset, MachineType rep);
     828        8800 :   TNode<Object> LoadObjectField(SloppyTNode<HeapObject> object,
     829             :                                 SloppyTNode<IntPtrT> offset) {
     830             :     return UncheckedCast<Object>(
     831        8800 :         LoadObjectField(object, offset, MachineType::AnyTagged()));
     832             :   }
     833             :   template <class T, typename std::enable_if<
     834             :                          std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
     835             :                          int>::type = 0>
     836           0 :   TNode<T> LoadObjectField(TNode<HeapObject> object, TNode<IntPtrT> offset) {
     837           0 :     return UncheckedCast<T>(
     838           0 :         LoadObjectField(object, offset, MachineTypeOf<T>::value));
     839             :   }
     840             :   // Load a SMI field and untag it.
     841             :   TNode<IntPtrT> LoadAndUntagObjectField(SloppyTNode<HeapObject> object,
     842             :                                          int offset);
     843             :   // Load a SMI field, untag it, and convert to Word32.
     844             :   TNode<Int32T> LoadAndUntagToWord32ObjectField(Node* object, int offset);
     845             :   // Load a SMI and untag it.
     846             :   TNode<IntPtrT> LoadAndUntagSmi(Node* base, int index);
     847             : 
     848        5936 :   TNode<MaybeObject> LoadMaybeWeakObjectField(SloppyTNode<HeapObject> object,
     849             :                                               int offset) {
     850             :     return UncheckedCast<MaybeObject>(
     851        5936 :         LoadObjectField(object, offset, MachineType::AnyTagged()));
     852             :   }
     853             : 
     854             :   // Tag a smi and store it.
     855             :   void StoreAndTagSmi(Node* base, int offset, Node* value);
     856             : 
     857             :   // Load the floating point value of a HeapNumber.
     858             :   TNode<Float64T> LoadHeapNumberValue(SloppyTNode<HeapNumber> object);
     859             :   // Load the Map of an HeapObject.
     860             :   TNode<Map> LoadMap(SloppyTNode<HeapObject> object);
     861             :   // Load the instance type of an HeapObject.
     862             :   TNode<Int32T> LoadInstanceType(SloppyTNode<HeapObject> object);
     863             :   // Compare the instance the type of the object against the provided one.
     864             :   TNode<BoolT> HasInstanceType(SloppyTNode<HeapObject> object,
     865             :                                InstanceType type);
     866             :   TNode<BoolT> DoesntHaveInstanceType(SloppyTNode<HeapObject> object,
     867             :                                       InstanceType type);
     868             :   TNode<BoolT> TaggedDoesntHaveInstanceType(SloppyTNode<HeapObject> any_tagged,
     869             :                                             InstanceType type);
     870             :   // Load the properties backing store of a JSObject.
     871             :   TNode<HeapObject> LoadSlowProperties(SloppyTNode<JSObject> object);
     872             :   TNode<HeapObject> LoadFastProperties(SloppyTNode<JSObject> object);
     873             :   // Load the elements backing store of a JSObject.
     874       19480 :   TNode<FixedArrayBase> LoadElements(SloppyTNode<JSObject> object) {
     875       19480 :     return LoadJSObjectElements(object);
     876             :   }
     877             :   // Load the length of a JSArray instance.
     878             :   TNode<Object> LoadJSArgumentsObjectWithLength(
     879             :       SloppyTNode<JSArgumentsObjectWithLength> array);
     880             :   // Load the length of a JSArray instance.
     881             :   TNode<Number> LoadJSArrayLength(SloppyTNode<JSArray> array);
     882             :   // Load the length of a fast JSArray instance. Returns a positive Smi.
     883             :   TNode<Smi> LoadFastJSArrayLength(SloppyTNode<JSArray> array);
     884             :   // Load the length of a fixed array base instance.
     885             :   TNode<Smi> LoadFixedArrayBaseLength(SloppyTNode<FixedArrayBase> array);
     886             :   // Load the length of a fixed array base instance.
     887             :   TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength(
     888             :       SloppyTNode<FixedArrayBase> array);
     889             :   // Load the length of a WeakFixedArray.
     890             :   TNode<Smi> LoadWeakFixedArrayLength(TNode<WeakFixedArray> array);
     891             :   TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength(
     892             :       SloppyTNode<WeakFixedArray> array);
     893             :   // Load the number of descriptors in DescriptorArray.
     894             :   TNode<Int32T> LoadNumberOfDescriptors(TNode<DescriptorArray> array);
     895             :   // Load the bit field of a Map.
     896             :   TNode<Int32T> LoadMapBitField(SloppyTNode<Map> map);
     897             :   // Load bit field 2 of a map.
     898             :   TNode<Int32T> LoadMapBitField2(SloppyTNode<Map> map);
     899             :   // Load bit field 3 of a map.
     900             :   TNode<Uint32T> LoadMapBitField3(SloppyTNode<Map> map);
     901             :   // Load the instance type of a map.
     902             :   TNode<Int32T> LoadMapInstanceType(SloppyTNode<Map> map);
     903             :   // Load the ElementsKind of a map.
     904             :   TNode<Int32T> LoadMapElementsKind(SloppyTNode<Map> map);
     905             :   TNode<Int32T> LoadElementsKind(SloppyTNode<HeapObject> object);
     906             :   // Load the instance descriptors of a map.
     907             :   TNode<DescriptorArray> LoadMapDescriptors(SloppyTNode<Map> map);
     908             :   // Load the prototype of a map.
     909             :   TNode<HeapObject> LoadMapPrototype(SloppyTNode<Map> map);
     910             :   // Load the prototype info of a map. The result has to be checked if it is a
     911             :   // prototype info object or not.
     912             :   TNode<PrototypeInfo> LoadMapPrototypeInfo(SloppyTNode<Map> map,
     913             :                                             Label* if_has_no_proto_info);
     914             :   // Load the instance size of a Map.
     915             :   TNode<IntPtrT> LoadMapInstanceSizeInWords(SloppyTNode<Map> map);
     916             :   // Load the inobject properties start of a Map (valid only for JSObjects).
     917             :   TNode<IntPtrT> LoadMapInobjectPropertiesStartInWords(SloppyTNode<Map> map);
     918             :   // Load the constructor function index of a Map (only for primitive maps).
     919             :   TNode<IntPtrT> LoadMapConstructorFunctionIndex(SloppyTNode<Map> map);
     920             :   // Load the constructor of a Map (equivalent to Map::GetConstructor()).
     921             :   TNode<Object> LoadMapConstructor(SloppyTNode<Map> map);
     922             :   // Load the EnumLength of a Map.
     923             :   Node* LoadMapEnumLength(SloppyTNode<Map> map);
     924             :   // Load the back-pointer of a Map.
     925             :   TNode<Object> LoadMapBackPointer(SloppyTNode<Map> map);
     926             :   // Checks that |map| has only simple properties, returns bitfield3.
     927             :   TNode<Uint32T> EnsureOnlyHasSimpleProperties(TNode<Map> map,
     928             :                                                TNode<Int32T> instance_type,
     929             :                                                Label* bailout);
     930             :   // Load the identity hash of a JSRececiver.
     931             :   TNode<IntPtrT> LoadJSReceiverIdentityHash(SloppyTNode<Object> receiver,
     932             :                                             Label* if_no_hash = nullptr);
     933             : 
     934             :   // This is only used on a newly allocated PropertyArray which
     935             :   // doesn't have an existing hash.
     936             :   void InitializePropertyArrayLength(Node* property_array, Node* length,
     937             :                                      ParameterMode mode);
     938             : 
     939             :   // Check if the map is set for slow properties.
     940             :   TNode<BoolT> IsDictionaryMap(SloppyTNode<Map> map);
     941             : 
     942             :   // Load the hash field of a name as an uint32 value.
     943             :   TNode<Uint32T> LoadNameHashField(SloppyTNode<Name> name);
     944             :   // Load the hash value of a name as an uint32 value.
     945             :   // If {if_hash_not_computed} label is specified then it also checks if
     946             :   // hash is actually computed.
     947             :   TNode<Uint32T> LoadNameHash(SloppyTNode<Name> name,
     948             :                               Label* if_hash_not_computed = nullptr);
     949             : 
     950             :   // Load length field of a String object as Smi value.
     951             :   TNode<Smi> LoadStringLengthAsSmi(SloppyTNode<String> string);
     952             :   // Load length field of a String object as intptr_t value.
     953             :   TNode<IntPtrT> LoadStringLengthAsWord(SloppyTNode<String> string);
     954             :   // Load length field of a String object as uint32_t value.
     955             :   TNode<Uint32T> LoadStringLengthAsWord32(SloppyTNode<String> string);
     956             :   // Loads a pointer to the sequential String char array.
     957             :   Node* PointerToSeqStringData(Node* seq_string);
     958             :   // Load value field of a JSValue object.
     959             :   Node* LoadJSValueValue(Node* object);
     960             : 
     961             :   // Figures out whether the value of maybe_object is:
     962             :   // - a SMI (jump to "if_smi", "extracted" will be the SMI value)
     963             :   // - a cleared weak reference (jump to "if_cleared", "extracted" will be
     964             :   // untouched)
     965             :   // - a weak reference (jump to "if_weak", "extracted" will be the object
     966             :   // pointed to)
     967             :   // - a strong reference (jump to "if_strong", "extracted" will be the object
     968             :   // pointed to)
     969             :   void DispatchMaybeObject(TNode<MaybeObject> maybe_object, Label* if_smi,
     970             :                            Label* if_cleared, Label* if_weak, Label* if_strong,
     971             :                            TVariable<Object>* extracted);
     972             :   // See MaybeObject for semantics of these functions.
     973             :   TNode<BoolT> IsStrong(TNode<MaybeObject> value);
     974             :   // This variant is for overzealous checking.
     975             :   TNode<BoolT> IsStrong(TNode<Object> value) {
     976             :     return IsStrong(ReinterpretCast<MaybeObject>(value));
     977             :   }
     978             :   TNode<HeapObject> GetHeapObjectIfStrong(TNode<MaybeObject> value,
     979             :                                           Label* if_not_strong);
     980             : 
     981             :   TNode<BoolT> IsWeakOrCleared(TNode<MaybeObject> value);
     982             :   TNode<BoolT> IsCleared(TNode<MaybeObject> value);
     983             :   TNode<BoolT> IsNotCleared(TNode<MaybeObject> value);
     984             : 
     985             :   // Removes the weak bit + asserts it was set.
     986             :   TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value);
     987             : 
     988             :   TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value,
     989             :                                             Label* if_cleared);
     990             : 
     991             :   TNode<BoolT> IsWeakReferenceTo(TNode<MaybeObject> object,
     992             :                                  TNode<Object> value);
     993             :   TNode<BoolT> IsNotWeakReferenceTo(TNode<MaybeObject> object,
     994             :                                     TNode<Object> value);
     995             :   TNode<BoolT> IsStrongReferenceTo(TNode<MaybeObject> object,
     996             :                                    TNode<Object> value);
     997             : 
     998             :   TNode<MaybeObject> MakeWeak(TNode<HeapObject> value);
     999             : 
    1000             :   void FixedArrayBoundsCheck(TNode<FixedArrayBase> array, Node* index,
    1001             :                              int additional_offset = 0,
    1002             :                              ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1003             : 
    1004             :   // Array is any array-like type that has a fixed header followed by
    1005             :   // tagged elements.
    1006             :   template <typename Array>
    1007             :   TNode<IntPtrT> LoadArrayLength(TNode<Array> array);
    1008             : 
    1009             :   // Array is any array-like type that has a fixed header followed by
    1010             :   // tagged elements.
    1011             :   template <typename Array>
    1012             :   TNode<MaybeObject> LoadArrayElement(
    1013             :       TNode<Array> array, int array_header_size, Node* index,
    1014             :       int additional_offset = 0,
    1015             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1016             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
    1017             : 
    1018             :   TNode<Object> LoadFixedArrayElement(
    1019             :       TNode<FixedArray> object, Node* index, int additional_offset = 0,
    1020             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1021             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe,
    1022             :       CheckBounds check_bounds = CheckBounds::kAlways);
    1023             : 
    1024             :   // This doesn't emit a bounds-check. As part of the security-performance
    1025             :   // tradeoff, only use it if it is performance critical.
    1026       34228 :   TNode<Object> UnsafeLoadFixedArrayElement(
    1027             :       TNode<FixedArray> object, Node* index, int additional_offset = 0,
    1028             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1029             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
    1030             :     return LoadFixedArrayElement(object, index, additional_offset,
    1031             :                                  parameter_mode, needs_poisoning,
    1032       34228 :                                  CheckBounds::kDebugOnly);
    1033             :   }
    1034             : 
    1035        7920 :   TNode<Object> LoadFixedArrayElement(
    1036             :       TNode<FixedArray> object, TNode<IntPtrT> index,
    1037             :       LoadSensitivity needs_poisoning,
    1038             :       CheckBounds check_bounds = CheckBounds::kAlways) {
    1039             :     return LoadFixedArrayElement(object, index, 0, INTPTR_PARAMETERS,
    1040        7920 :                                  needs_poisoning, check_bounds);
    1041             :   }
    1042             :   // This doesn't emit a bounds-check. As part of the security-performance
    1043             :   // tradeoff, only use it if it is performance critical.
    1044        7920 :   TNode<Object> UnsafeLoadFixedArrayElement(TNode<FixedArray> object,
    1045             :                                             TNode<IntPtrT> index,
    1046             :                                             LoadSensitivity needs_poisoning) {
    1047             :     return LoadFixedArrayElement(object, index, needs_poisoning,
    1048        7920 :                                  CheckBounds::kDebugOnly);
    1049             :   }
    1050             : 
    1051        9040 :   TNode<Object> LoadFixedArrayElement(
    1052             :       TNode<FixedArray> object, TNode<IntPtrT> index, int additional_offset = 0,
    1053             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
    1054             :     return LoadFixedArrayElement(object, index, additional_offset,
    1055       14272 :                                  INTPTR_PARAMETERS, needs_poisoning);
    1056             :   }
    1057             : 
    1058        9872 :   TNode<Object> LoadFixedArrayElement(
    1059             :       TNode<FixedArray> object, int index, int additional_offset = 0,
    1060             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
    1061       19744 :     return LoadFixedArrayElement(object, IntPtrConstant(index),
    1062             :                                  additional_offset, INTPTR_PARAMETERS,
    1063       19744 :                                  needs_poisoning);
    1064             :   }
    1065             :   // This doesn't emit a bounds-check. As part of the security-performance
    1066             :   // tradeoff, only use it if it is performance critical.
    1067       19296 :   TNode<Object> UnsafeLoadFixedArrayElement(
    1068             :       TNode<FixedArray> object, int index, int additional_offset = 0,
    1069             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
    1070       38592 :     return LoadFixedArrayElement(object, IntPtrConstant(index),
    1071             :                                  additional_offset, INTPTR_PARAMETERS,
    1072       38592 :                                  needs_poisoning, CheckBounds::kDebugOnly);
    1073             :   }
    1074        5600 :   TNode<Object> LoadFixedArrayElement(TNode<FixedArray> object,
    1075             :                                       TNode<Smi> index) {
    1076        5600 :     return LoadFixedArrayElement(object, index, 0, SMI_PARAMETERS);
    1077             :   }
    1078             : 
    1079             :   TNode<Object> LoadPropertyArrayElement(TNode<PropertyArray> object,
    1080             :                                          SloppyTNode<IntPtrT> index);
    1081             :   TNode<IntPtrT> LoadPropertyArrayLength(TNode<PropertyArray> object);
    1082             : 
    1083             :   // Load an element from an array and untag it and return it as Word32.
    1084             :   // Array is any array-like type that has a fixed header followed by
    1085             :   // tagged elements.
    1086             :   template <typename Array>
    1087             :   TNode<Int32T> LoadAndUntagToWord32ArrayElement(
    1088             :       TNode<Array> array, int array_header_size, Node* index,
    1089             :       int additional_offset = 0,
    1090             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1091             : 
    1092             :   // Load an array element from a FixedArray, untag it and return it as Word32.
    1093             :   TNode<Int32T> LoadAndUntagToWord32FixedArrayElement(
    1094             :       TNode<FixedArray> object, Node* index, int additional_offset = 0,
    1095             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1096             : 
    1097             :   TNode<Int32T> LoadAndUntagToWord32FixedArrayElement(
    1098             :       TNode<FixedArray> object, int index, int additional_offset = 0) {
    1099             :     return LoadAndUntagToWord32FixedArrayElement(
    1100             :         object, IntPtrConstant(index), additional_offset, INTPTR_PARAMETERS);
    1101             :   }
    1102             : 
    1103             :   // Load an array element from a WeakFixedArray.
    1104             :   TNode<MaybeObject> LoadWeakFixedArrayElement(
    1105             :       TNode<WeakFixedArray> object, Node* index, int additional_offset = 0,
    1106             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1107             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
    1108             : 
    1109             :   TNode<MaybeObject> LoadWeakFixedArrayElement(
    1110             :       TNode<WeakFixedArray> object, int index, int additional_offset = 0,
    1111             :       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
    1112             :     return LoadWeakFixedArrayElement(object, IntPtrConstant(index),
    1113             :                                      additional_offset, INTPTR_PARAMETERS,
    1114             :                                      needs_poisoning);
    1115             :   }
    1116             : 
    1117             :   // Load an array element from a FixedDoubleArray.
    1118             :   TNode<Float64T> LoadFixedDoubleArrayElement(
    1119             :       SloppyTNode<FixedDoubleArray> object, Node* index,
    1120             :       MachineType machine_type, int additional_offset = 0,
    1121             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1122             :       Label* if_hole = nullptr);
    1123             : 
    1124             :   Node* LoadFixedDoubleArrayElement(TNode<FixedDoubleArray> object,
    1125             :                                     TNode<Smi> index,
    1126             :                                     Label* if_hole = nullptr) {
    1127             :     return LoadFixedDoubleArrayElement(object, index, MachineType::Float64(), 0,
    1128             :                                        SMI_PARAMETERS, if_hole);
    1129             :   }
    1130             : 
    1131          56 :   Node* LoadFixedDoubleArrayElement(TNode<FixedDoubleArray> object,
    1132             :                                     TNode<IntPtrT> index,
    1133             :                                     Label* if_hole = nullptr) {
    1134         112 :     return LoadFixedDoubleArrayElement(object, index, MachineType::Float64(), 0,
    1135         168 :                                        INTPTR_PARAMETERS, if_hole);
    1136             :   }
    1137             : 
    1138             :   // Load an array element from a FixedArray, FixedDoubleArray or a
    1139             :   // NumberDictionary (depending on the |elements_kind|) and return
    1140             :   // it as a tagged value. Assumes that the |index| passed a length
    1141             :   // check before. Bails out to |if_accessor| if the element that
    1142             :   // was found is an accessor, or to |if_hole| if the element at
    1143             :   // the given |index| is not found in |elements|.
    1144             :   TNode<Object> LoadFixedArrayBaseElementAsTagged(
    1145             :       TNode<FixedArrayBase> elements, TNode<IntPtrT> index,
    1146             :       TNode<Int32T> elements_kind, Label* if_accessor, Label* if_hole);
    1147             : 
    1148             :   // Load a feedback slot from a FeedbackVector.
    1149             :   TNode<MaybeObject> LoadFeedbackVectorSlot(
    1150             :       Node* object, Node* index, int additional_offset = 0,
    1151             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1152             : 
    1153             :   TNode<IntPtrT> LoadFeedbackVectorLength(TNode<FeedbackVector>);
    1154             :   TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array,
    1155             :                                           TNode<Smi> index,
    1156             :                                           Label* if_hole = nullptr);
    1157             :   TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array,
    1158             :                                           TNode<IntPtrT> index,
    1159             :                                           Label* if_hole = nullptr);
    1160             : 
    1161             :   // Load Float64 value by |base| + |offset| address. If the value is a double
    1162             :   // hole then jump to |if_hole|. If |machine_type| is None then only the hole
    1163             :   // check is generated.
    1164             :   TNode<Float64T> LoadDoubleWithHoleCheck(
    1165             :       SloppyTNode<Object> base, SloppyTNode<IntPtrT> offset, Label* if_hole,
    1166             :       MachineType machine_type = MachineType::Float64());
    1167             :   TNode<RawPtrT> LoadFixedTypedArrayBackingStore(
    1168             :       TNode<FixedTypedArrayBase> typed_array);
    1169             :   TNode<RawPtrT> LoadFixedTypedArrayOnHeapBackingStore(
    1170             :       TNode<FixedTypedArrayBase> typed_array);
    1171             :   Node* LoadFixedTypedArrayElementAsTagged(
    1172             :       Node* data_pointer, Node* index_node, ElementsKind elements_kind,
    1173             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1174             :   TNode<Numeric> LoadFixedTypedArrayElementAsTagged(
    1175             :       TNode<WordT> data_pointer, TNode<Smi> index, TNode<Int32T> elements_kind);
    1176             :   // Parts of the above, factored out for readability:
    1177             :   Node* LoadFixedBigInt64ArrayElementAsTagged(Node* data_pointer, Node* offset);
    1178             :   Node* LoadFixedBigUint64ArrayElementAsTagged(Node* data_pointer,
    1179             :                                                Node* offset);
    1180             :   // 64-bit platforms only:
    1181             :   TNode<BigInt> BigIntFromInt64(TNode<IntPtrT> value);
    1182             :   TNode<BigInt> BigIntFromUint64(TNode<UintPtrT> value);
    1183             :   // 32-bit platforms only:
    1184             :   TNode<BigInt> BigIntFromInt32Pair(TNode<IntPtrT> low, TNode<IntPtrT> high);
    1185             :   TNode<BigInt> BigIntFromUint32Pair(TNode<UintPtrT> low, TNode<UintPtrT> high);
    1186             : 
    1187             :   void StoreFixedTypedArrayElementFromTagged(
    1188             :       TNode<Context> context, TNode<FixedTypedArrayBase> elements,
    1189             :       TNode<Object> index_node, TNode<Object> value, ElementsKind elements_kind,
    1190             :       ParameterMode parameter_mode);
    1191             : 
    1192             :   // Context manipulation
    1193             :   TNode<Object> LoadContextElement(SloppyTNode<Context> context,
    1194             :                                    int slot_index);
    1195             :   TNode<Object> LoadContextElement(SloppyTNode<Context> context,
    1196             :                                    SloppyTNode<IntPtrT> slot_index);
    1197             :   TNode<Object> LoadContextElement(TNode<Context> context,
    1198             :                                    TNode<Smi> slot_index);
    1199             :   void StoreContextElement(SloppyTNode<Context> context, int slot_index,
    1200             :                            SloppyTNode<Object> value);
    1201             :   void StoreContextElement(SloppyTNode<Context> context,
    1202             :                            SloppyTNode<IntPtrT> slot_index,
    1203             :                            SloppyTNode<Object> value);
    1204             :   void StoreContextElementNoWriteBarrier(SloppyTNode<Context> context,
    1205             :                                          int slot_index,
    1206             :                                          SloppyTNode<Object> value);
    1207             :   TNode<Context> LoadNativeContext(SloppyTNode<Context> context);
    1208             :   // Calling this is only valid if there's a module context in the chain.
    1209             :   TNode<Context> LoadModuleContext(SloppyTNode<Context> context);
    1210             : 
    1211             :   void GotoIfContextElementEqual(Node* value, Node* native_context,
    1212             :                                  int slot_index, Label* if_equal) {
    1213             :     GotoIf(WordEqual(value, LoadContextElement(native_context, slot_index)),
    1214             :            if_equal);
    1215             :   }
    1216             : 
    1217             :   TNode<Map> LoadJSArrayElementsMap(ElementsKind kind,
    1218             :                                     SloppyTNode<Context> native_context);
    1219             :   TNode<Map> LoadJSArrayElementsMap(SloppyTNode<Int32T> kind,
    1220             :                                     SloppyTNode<Context> native_context);
    1221             : 
    1222             :   TNode<BoolT> IsGeneratorFunction(TNode<JSFunction> function);
    1223             :   TNode<BoolT> HasPrototypeProperty(TNode<JSFunction> function, TNode<Map> map);
    1224             :   void GotoIfPrototypeRequiresRuntimeLookup(TNode<JSFunction> function,
    1225             :                                             TNode<Map> map, Label* runtime);
    1226             :   // Load the "prototype" property of a JSFunction.
    1227             :   Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout);
    1228             : 
    1229             :   TNode<BytecodeArray> LoadSharedFunctionInfoBytecodeArray(
    1230             :       SloppyTNode<SharedFunctionInfo> shared);
    1231             : 
    1232             :   void StoreObjectByteNoWriteBarrier(TNode<HeapObject> object, int offset,
    1233             :                                      TNode<Word32T> value);
    1234             : 
    1235             :   // Store the floating point value of a HeapNumber.
    1236             :   void StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
    1237             :                             SloppyTNode<Float64T> value);
    1238             :   void StoreMutableHeapNumberValue(SloppyTNode<MutableHeapNumber> object,
    1239             :                                    SloppyTNode<Float64T> value);
    1240             :   // Store a field to an object on the heap.
    1241             :   void StoreObjectField(Node* object, int offset, Node* value);
    1242             :   void StoreObjectField(Node* object, Node* offset, Node* value);
    1243             :   void StoreObjectFieldNoWriteBarrier(
    1244             :       Node* object, int offset, Node* value,
    1245             :       MachineRepresentation rep = MachineRepresentation::kTagged);
    1246             :   void StoreObjectFieldNoWriteBarrier(
    1247             :       Node* object, Node* offset, Node* value,
    1248             :       MachineRepresentation rep = MachineRepresentation::kTagged);
    1249             : 
    1250             :   template <class T = Object>
    1251         672 :   void StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object,
    1252             :                                       TNode<IntPtrT> offset, TNode<T> value) {
    1253         672 :     StoreObjectFieldNoWriteBarrier(object, offset, value,
    1254             :                                    MachineRepresentationOf<T>::value);
    1255         672 :   }
    1256             :   template <class T = Object>
    1257       14916 :   void StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object, int offset,
    1258             :                                       TNode<T> value) {
    1259       14916 :     StoreObjectFieldNoWriteBarrier(object, offset, value,
    1260             :                                    MachineRepresentationOf<T>::value);
    1261       14916 :   }
    1262             : 
    1263             :   // Store the Map of an HeapObject.
    1264             :   void StoreMap(Node* object, Node* map);
    1265             :   void StoreMapNoWriteBarrier(Node* object, RootIndex map_root_index);
    1266             :   void StoreMapNoWriteBarrier(Node* object, Node* map);
    1267             :   void StoreObjectFieldRoot(Node* object, int offset, RootIndex root);
    1268             :   // Store an array element to a FixedArray.
    1269       20428 :   void StoreFixedArrayElement(
    1270             :       TNode<FixedArray> object, int index, SloppyTNode<Object> value,
    1271             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1272             :       CheckBounds check_bounds = CheckBounds::kAlways) {
    1273       40856 :     return StoreFixedArrayElement(object, IntPtrConstant(index), value,
    1274             :                                   barrier_mode, 0, INTPTR_PARAMETERS,
    1275       40856 :                                   check_bounds);
    1276             :   }
    1277             :   // This doesn't emit a bounds-check. As part of the security-performance
    1278             :   // tradeoff, only use it if it is performance critical.
    1279        2800 :   void UnsafeStoreFixedArrayElement(
    1280             :       TNode<FixedArray> object, int index, SloppyTNode<Object> value,
    1281             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
    1282             :     return StoreFixedArrayElement(object, index, value, barrier_mode,
    1283        2800 :                                   CheckBounds::kDebugOnly);
    1284             :   }
    1285        3184 :   void StoreFixedArrayElement(TNode<FixedArray> object, int index,
    1286             :                               TNode<Smi> value,
    1287             :                               CheckBounds check_bounds = CheckBounds::kAlways) {
    1288        6368 :     return StoreFixedArrayElement(object, IntPtrConstant(index), value,
    1289             :                                   SKIP_WRITE_BARRIER, 0, INTPTR_PARAMETERS,
    1290        6368 :                                   check_bounds);
    1291             :   }
    1292             :   // This doesn't emit a bounds-check. As part of the security-performance
    1293             :   // tradeoff, only use it if it is performance critical.
    1294        1456 :   void UnsafeStoreFixedArrayElement(TNode<FixedArray> object, int index,
    1295             :                                     TNode<Smi> value) {
    1296             :     return StoreFixedArrayElement(object, index, value,
    1297        1456 :                                   CheckBounds::kDebugOnly);
    1298             :   }
    1299             : 
    1300             :   void StoreJSArrayLength(TNode<JSArray> array, TNode<Smi> length);
    1301             :   void StoreElements(TNode<Object> object, TNode<FixedArrayBase> elements);
    1302             : 
    1303             :   void StoreFixedArrayOrPropertyArrayElement(
    1304             :       Node* array, Node* index, Node* value,
    1305             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1306             :       int additional_offset = 0,
    1307             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1308             : 
    1309       38700 :   void StoreFixedArrayElement(
    1310             :       TNode<FixedArray> array, Node* index, SloppyTNode<Object> value,
    1311             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1312             :       int additional_offset = 0,
    1313             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1314             :       CheckBounds check_bounds = CheckBounds::kAlways) {
    1315       38700 :     if (NeedsBoundsCheck(check_bounds)) {
    1316       33380 :       FixedArrayBoundsCheck(array, index, additional_offset, parameter_mode);
    1317             :     }
    1318       16784 :     StoreFixedArrayOrPropertyArrayElement(array, index, value, barrier_mode,
    1319       38700 :                                           additional_offset, parameter_mode);
    1320       38700 :   }
    1321             : 
    1322             :   // This doesn't emit a bounds-check. As part of the security-performance
    1323             :   // tradeoff, only use it if it is performance critical.
    1324        1064 :   void UnsafeStoreFixedArrayElement(
    1325             :       TNode<FixedArray> array, Node* index, SloppyTNode<Object> value,
    1326             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1327             :       int additional_offset = 0,
    1328             :       ParameterMode parameter_mode = INTPTR_PARAMETERS) {
    1329             :     return StoreFixedArrayElement(array, index, value, barrier_mode,
    1330             :                                   additional_offset, parameter_mode,
    1331        1064 :                                   CheckBounds::kDebugOnly);
    1332             :   }
    1333             : 
    1334         728 :   void StorePropertyArrayElement(
    1335             :       TNode<PropertyArray> array, Node* index, SloppyTNode<Object> value,
    1336             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1337             :       int additional_offset = 0,
    1338             :       ParameterMode parameter_mode = INTPTR_PARAMETERS) {
    1339         728 :     StoreFixedArrayOrPropertyArrayElement(array, index, value, barrier_mode,
    1340         728 :                                           additional_offset, parameter_mode);
    1341         728 :   }
    1342             : 
    1343        2184 :   void StoreFixedArrayElementSmi(
    1344             :       TNode<FixedArray> array, TNode<Smi> index, TNode<Object> value,
    1345             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
    1346        4368 :     StoreFixedArrayElement(array, index, value, barrier_mode, 0,
    1347        2184 :                            SMI_PARAMETERS);
    1348        2184 :   }
    1349         896 :   void StoreFixedArrayElement(TNode<FixedArray> array, TNode<IntPtrT> index,
    1350             :                               TNode<Smi> value) {
    1351         896 :     StoreFixedArrayElement(array, index, value, SKIP_WRITE_BARRIER, 0);
    1352         896 :   }
    1353         336 :   void StoreFixedArrayElement(TNode<FixedArray> array, TNode<Smi> index,
    1354             :                               TNode<Smi> value) {
    1355         672 :     StoreFixedArrayElement(array, index, value, SKIP_WRITE_BARRIER, 0,
    1356         336 :                            SMI_PARAMETERS);
    1357         336 :   }
    1358             : 
    1359             :   void StoreFixedDoubleArrayElement(
    1360             :       TNode<FixedDoubleArray> object, Node* index, TNode<Float64T> value,
    1361             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1362             :       CheckBounds check_bounds = CheckBounds::kAlways);
    1363             :   // This doesn't emit a bounds-check. As part of the security-performance
    1364             :   // tradeoff, only use it if it is performance critical.
    1365             :   void UnsafeStoreFixedDoubleArrayElement(
    1366             :       TNode<FixedDoubleArray> object, Node* index, TNode<Float64T> value,
    1367             :       ParameterMode parameter_mode = INTPTR_PARAMETERS) {
    1368             :     return StoreFixedDoubleArrayElement(object, index, value, parameter_mode,
    1369             :                                         CheckBounds::kDebugOnly);
    1370             :   }
    1371             : 
    1372         392 :   void StoreFixedDoubleArrayElementSmi(TNode<FixedDoubleArray> object,
    1373             :                                        TNode<Smi> index,
    1374             :                                        TNode<Float64T> value) {
    1375         392 :     StoreFixedDoubleArrayElement(object, index, value, SMI_PARAMETERS);
    1376         392 :   }
    1377             : 
    1378             :   void StoreFixedDoubleArrayHole(TNode<FixedDoubleArray> array, Node* index,
    1379             :                                  ParameterMode mode = INTPTR_PARAMETERS);
    1380          56 :   void StoreFixedDoubleArrayHoleSmi(TNode<FixedDoubleArray> array,
    1381             :                                     TNode<Smi> index) {
    1382          56 :     StoreFixedDoubleArrayHole(array, index, SMI_PARAMETERS);
    1383          56 :   }
    1384             : 
    1385             :   void StoreFeedbackVectorSlot(
    1386             :       Node* object, Node* index, Node* value,
    1387             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1388             :       int additional_offset = 0,
    1389             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1390             : 
    1391             :   void EnsureArrayLengthWritable(TNode<Map> map, Label* bailout);
    1392             : 
    1393             :   // EnsureArrayPushable verifies that receiver with this map is:
    1394             :   //   1. Is not a prototype.
    1395             :   //   2. Is not a dictionary.
    1396             :   //   3. Has a writeable length property.
    1397             :   // It returns ElementsKind as a node for further division into cases.
    1398             :   TNode<Int32T> EnsureArrayPushable(TNode<Map> map, Label* bailout);
    1399             : 
    1400             :   void TryStoreArrayElement(ElementsKind kind, ParameterMode mode,
    1401             :                             Label* bailout, Node* elements, Node* index,
    1402             :                             Node* value);
    1403             :   // Consumes args into the array, and returns tagged new length.
    1404             :   TNode<Smi> BuildAppendJSArray(ElementsKind kind, SloppyTNode<JSArray> array,
    1405             :                                 CodeStubArguments* args,
    1406             :                                 TVariable<IntPtrT>* arg_index, Label* bailout);
    1407             :   // Pushes value onto the end of array.
    1408             :   void BuildAppendJSArray(ElementsKind kind, Node* array, Node* value,
    1409             :                           Label* bailout);
    1410             : 
    1411             :   void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address,
    1412             :                                  Node* value);
    1413             : 
    1414             :   Node* AllocateCellWithValue(Node* value,
    1415             :                               WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    1416             :   Node* AllocateSmiCell(int value = 0) {
    1417             :     return AllocateCellWithValue(SmiConstant(value), SKIP_WRITE_BARRIER);
    1418             :   }
    1419             : 
    1420             :   Node* LoadCellValue(Node* cell);
    1421             : 
    1422             :   void StoreCellValue(Node* cell, Node* value,
    1423             :                       WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
    1424             : 
    1425             :   // Allocate a HeapNumber without initializing its value.
    1426             :   TNode<HeapNumber> AllocateHeapNumber();
    1427             :   // Allocate a HeapNumber with a specific value.
    1428             :   TNode<HeapNumber> AllocateHeapNumberWithValue(SloppyTNode<Float64T> value);
    1429             :   TNode<HeapNumber> AllocateHeapNumberWithValue(double value) {
    1430             :     return AllocateHeapNumberWithValue(Float64Constant(value));
    1431             :   }
    1432             : 
    1433             :   // Allocate a MutableHeapNumber with a specific value.
    1434             :   TNode<MutableHeapNumber> AllocateMutableHeapNumberWithValue(
    1435             :       SloppyTNode<Float64T> value);
    1436             : 
    1437             :   // Allocate a BigInt with {length} digits. Sets the sign bit to {false}.
    1438             :   // Does not initialize the digits.
    1439             :   TNode<BigInt> AllocateBigInt(TNode<IntPtrT> length);
    1440             :   // Like above, but allowing custom bitfield initialization.
    1441             :   TNode<BigInt> AllocateRawBigInt(TNode<IntPtrT> length);
    1442             :   void StoreBigIntBitfield(TNode<BigInt> bigint, TNode<Word32T> bitfield);
    1443             :   void StoreBigIntDigit(TNode<BigInt> bigint, int digit_index,
    1444             :                         TNode<UintPtrT> digit);
    1445             :   TNode<Word32T> LoadBigIntBitfield(TNode<BigInt> bigint);
    1446             :   TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, int digit_index);
    1447             : 
    1448             :   // Allocate a SeqOneByteString with the given length.
    1449             :   TNode<String> AllocateSeqOneByteString(uint32_t length,
    1450             :                                          AllocationFlags flags = kNone);
    1451             :   TNode<String> AllocateSeqOneByteString(Node* context, TNode<Uint32T> length,
    1452             :                                          AllocationFlags flags = kNone);
    1453             :   // Allocate a SeqTwoByteString with the given length.
    1454             :   TNode<String> AllocateSeqTwoByteString(uint32_t length,
    1455             :                                          AllocationFlags flags = kNone);
    1456             :   TNode<String> AllocateSeqTwoByteString(Node* context, TNode<Uint32T> length,
    1457             :                                          AllocationFlags flags = kNone);
    1458             : 
    1459             :   // Allocate a SlicedOneByteString with the given length, parent and offset.
    1460             :   // |length| and |offset| are expected to be tagged.
    1461             : 
    1462             :   TNode<String> AllocateSlicedOneByteString(TNode<Uint32T> length,
    1463             :                                             TNode<String> parent,
    1464             :                                             TNode<Smi> offset);
    1465             :   // Allocate a SlicedTwoByteString with the given length, parent and offset.
    1466             :   // |length| and |offset| are expected to be tagged.
    1467             :   TNode<String> AllocateSlicedTwoByteString(TNode<Uint32T> length,
    1468             :                                             TNode<String> parent,
    1469             :                                             TNode<Smi> offset);
    1470             : 
    1471             :   // Allocate an appropriate one- or two-byte ConsString with the first and
    1472             :   // second parts specified by |left| and |right|.
    1473             :   TNode<String> AllocateConsString(TNode<Uint32T> length, TNode<String> left,
    1474             :                                    TNode<String> right, Variable* var_feedback);
    1475             : 
    1476             :   TNode<NameDictionary> AllocateNameDictionary(int at_least_space_for);
    1477             :   TNode<NameDictionary> AllocateNameDictionary(
    1478             :       TNode<IntPtrT> at_least_space_for);
    1479             :   TNode<NameDictionary> AllocateNameDictionaryWithCapacity(
    1480             :       TNode<IntPtrT> capacity);
    1481             :   TNode<NameDictionary> CopyNameDictionary(TNode<NameDictionary> dictionary,
    1482             :                                            Label* large_object_fallback);
    1483             : 
    1484             :   template <typename CollectionType>
    1485             :   Node* AllocateOrderedHashTable();
    1486             : 
    1487             :   // Builds code that finds OrderedHashTable entry for a key with hash code
    1488             :   // {hash} with using the comparison code generated by {key_compare}. The code
    1489             :   // jumps to {entry_found} if the key is found, or to {not_found} if the key
    1490             :   // was not found. In the {entry_found} branch, the variable
    1491             :   // entry_start_position will be bound to the index of the entry (relative to
    1492             :   // OrderedHashTable::kHashTableStartIndex).
    1493             :   //
    1494             :   // The {CollectionType} template parameter stands for the particular instance
    1495             :   // of OrderedHashTable, it should be OrderedHashMap or OrderedHashSet.
    1496             :   template <typename CollectionType>
    1497             :   void FindOrderedHashTableEntry(
    1498             :       Node* table, Node* hash,
    1499             :       const std::function<void(Node*, Label*, Label*)>& key_compare,
    1500             :       Variable* entry_start_position, Label* entry_found, Label* not_found);
    1501             : 
    1502             :   template <typename CollectionType>
    1503             :   TNode<CollectionType> AllocateSmallOrderedHashTable(TNode<IntPtrT> capacity);
    1504             : 
    1505             :   Node* AllocateStruct(Node* map, AllocationFlags flags = kNone);
    1506             :   void InitializeStructBody(Node* object, Node* map, Node* size,
    1507             :                             int start_offset = Struct::kHeaderSize);
    1508             : 
    1509             :   Node* AllocateJSObjectFromMap(
    1510             :       Node* map, Node* properties = nullptr, Node* elements = nullptr,
    1511             :       AllocationFlags flags = kNone,
    1512             :       SlackTrackingMode slack_tracking_mode = kNoSlackTracking);
    1513             : 
    1514             :   void InitializeJSObjectFromMap(
    1515             :       Node* object, Node* map, Node* instance_size, Node* properties = nullptr,
    1516             :       Node* elements = nullptr,
    1517             :       SlackTrackingMode slack_tracking_mode = kNoSlackTracking);
    1518             : 
    1519             :   void InitializeJSObjectBodyWithSlackTracking(Node* object, Node* map,
    1520             :                                                Node* instance_size);
    1521             :   void InitializeJSObjectBodyNoSlackTracking(
    1522             :       Node* object, Node* map, Node* instance_size,
    1523             :       int start_offset = JSObject::kHeaderSize);
    1524             : 
    1525             :   TNode<BoolT> IsValidFastJSArrayCapacity(Node* capacity,
    1526             :                                           ParameterMode capacity_mode);
    1527             : 
    1528             :   //
    1529             :   // Allocate and return a JSArray with initialized header fields and its
    1530             :   // uninitialized elements.
    1531             :   // The ParameterMode argument is only used for the capacity parameter.
    1532             :   std::pair<TNode<JSArray>, TNode<FixedArrayBase>>
    1533             :   AllocateUninitializedJSArrayWithElements(
    1534             :       ElementsKind kind, TNode<Map> array_map, TNode<Smi> length,
    1535             :       Node* allocation_site, Node* capacity,
    1536             :       ParameterMode capacity_mode = INTPTR_PARAMETERS,
    1537             :       AllocationFlags allocation_flags = kNone);
    1538             : 
    1539             :   // Allocate a JSArray and fill elements with the hole.
    1540             :   // The ParameterMode argument is only used for the capacity parameter.
    1541             :   TNode<JSArray> AllocateJSArray(
    1542             :       ElementsKind kind, TNode<Map> array_map, Node* capacity,
    1543             :       TNode<Smi> length, Node* allocation_site = nullptr,
    1544             :       ParameterMode capacity_mode = INTPTR_PARAMETERS,
    1545             :       AllocationFlags allocation_flags = kNone);
    1546             : 
    1547         224 :   TNode<JSArray> AllocateJSArray(ElementsKind kind, TNode<Map> array_map,
    1548             :                                  TNode<Smi> capacity, TNode<Smi> length) {
    1549             :     return AllocateJSArray(kind, array_map, capacity, length, nullptr,
    1550         224 :                            SMI_PARAMETERS);
    1551             :   }
    1552             : 
    1553         336 :   TNode<JSArray> AllocateJSArray(ElementsKind kind, TNode<Map> array_map,
    1554             :                                  TNode<IntPtrT> capacity, TNode<Smi> length) {
    1555             :     return AllocateJSArray(kind, array_map, capacity, length, nullptr,
    1556         336 :                            INTPTR_PARAMETERS);
    1557             :   }
    1558             : 
    1559             :   // Allocate a JSArray and initialize the header fields.
    1560             :   TNode<JSArray> AllocateJSArray(TNode<Map> array_map,
    1561             :                                  TNode<FixedArrayBase> elements,
    1562             :                                  TNode<Smi> length,
    1563             :                                  Node* allocation_site = nullptr);
    1564             : 
    1565             :   enum class HoleConversionMode { kDontConvert, kConvertToUndefined };
    1566             :   // Clone a fast JSArray |array| into a new fast JSArray.
    1567             :   // |convert_holes| tells the function to convert holes into undefined or not.
    1568             :   // If |convert_holes| is set to kConvertToUndefined, but the function did not
    1569             :   // find any hole in |array|, the resulting array will have the same elements
    1570             :   // kind as |array|. If the function did find a hole, it will convert holes in
    1571             :   // |array| to undefined in the resulting array, who will now have
    1572             :   // PACKED_ELEMENTS kind.
    1573             :   // If |convert_holes| is set kDontConvert, holes are also copied to the
    1574             :   // resulting array, who will have the same elements kind as |array|. The
    1575             :   // function generates significantly less code in this case.
    1576             :   Node* CloneFastJSArray(
    1577             :       Node* context, Node* array, ParameterMode mode = INTPTR_PARAMETERS,
    1578             :       Node* allocation_site = nullptr,
    1579             :       HoleConversionMode convert_holes = HoleConversionMode::kDontConvert);
    1580             : 
    1581             :   Node* ExtractFastJSArray(Node* context, Node* array, Node* begin, Node* count,
    1582             :                            ParameterMode mode = INTPTR_PARAMETERS,
    1583             :                            Node* capacity = nullptr,
    1584             :                            Node* allocation_site = nullptr);
    1585             : 
    1586             :   TNode<FixedArrayBase> AllocateFixedArray(
    1587             :       ElementsKind kind, Node* capacity, ParameterMode mode = INTPTR_PARAMETERS,
    1588             :       AllocationFlags flags = kNone,
    1589             :       SloppyTNode<Map> fixed_array_map = nullptr);
    1590             : 
    1591        1848 :   TNode<FixedArrayBase> AllocateFixedArray(
    1592             :       ElementsKind kind, TNode<IntPtrT> capacity, AllocationFlags flags,
    1593             :       SloppyTNode<Map> fixed_array_map = nullptr) {
    1594             :     return AllocateFixedArray(kind, capacity, INTPTR_PARAMETERS, flags,
    1595        2304 :                               fixed_array_map);
    1596             :   }
    1597             : 
    1598          56 :   TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) {
    1599             :     return UncheckedCast<FixedArray>(AllocateFixedArray(
    1600          56 :         PACKED_ELEMENTS, IntPtrConstant(capacity), AllocationFlag::kNone));
    1601             :   }
    1602             : 
    1603        1016 :   TNode<FixedArray> AllocateZeroedFixedArray(TNode<IntPtrT> capacity) {
    1604             :     TNode<FixedArray> result = UncheckedCast<FixedArray>(
    1605             :         AllocateFixedArray(PACKED_ELEMENTS, capacity,
    1606         560 :                            AllocationFlag::kAllowLargeObjectAllocation));
    1607        1016 :     FillFixedArrayWithSmiZero(result, capacity);
    1608        1016 :     return result;
    1609             :   }
    1610             : 
    1611          56 :   TNode<FixedDoubleArray> AllocateZeroedFixedDoubleArray(
    1612             :       TNode<IntPtrT> capacity) {
    1613             :     TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
    1614             :         AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity,
    1615          56 :                            AllocationFlag::kAllowLargeObjectAllocation));
    1616          56 :     FillFixedDoubleArrayWithZero(result, capacity);
    1617          56 :     return result;
    1618             :   }
    1619             : 
    1620         336 :   TNode<FixedArray> AllocateFixedArrayWithHoles(TNode<IntPtrT> capacity,
    1621             :                                                 AllocationFlags flags) {
    1622             :     TNode<FixedArray> result = UncheckedCast<FixedArray>(
    1623         336 :         AllocateFixedArray(PACKED_ELEMENTS, capacity, flags));
    1624         672 :     FillFixedArrayWithValue(PACKED_ELEMENTS, result, IntPtrConstant(0),
    1625         336 :                             capacity, RootIndex::kTheHoleValue);
    1626         336 :     return result;
    1627             :   }
    1628             : 
    1629         112 :   TNode<FixedDoubleArray> AllocateFixedDoubleArrayWithHoles(
    1630             :       TNode<IntPtrT> capacity, AllocationFlags flags) {
    1631             :     TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
    1632         112 :         AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity, flags));
    1633         224 :     FillFixedArrayWithValue(PACKED_DOUBLE_ELEMENTS, result, IntPtrConstant(0),
    1634         112 :                             capacity, RootIndex::kTheHoleValue);
    1635         112 :     return result;
    1636             :   }
    1637             : 
    1638             :   Node* AllocatePropertyArray(Node* capacity,
    1639             :                               ParameterMode mode = INTPTR_PARAMETERS,
    1640             :                               AllocationFlags flags = kNone);
    1641             : 
    1642             :   // Perform CreateArrayIterator (ES #sec-createarrayiterator).
    1643             :   TNode<JSArrayIterator> CreateArrayIterator(TNode<Context> context,
    1644             :                                              TNode<Object> object,
    1645             :                                              IterationKind mode);
    1646             : 
    1647             :   Node* AllocateJSIteratorResult(Node* context, Node* value, Node* done);
    1648             :   Node* AllocateJSIteratorResultForEntry(Node* context, Node* key, Node* value);
    1649             : 
    1650             :   TNode<JSReceiver> ArraySpeciesCreate(TNode<Context> context,
    1651             :                                        TNode<Object> originalArray,
    1652             :                                        TNode<Number> len);
    1653             : 
    1654             :   void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index,
    1655             :                                Node* to_index, RootIndex value_root_index,
    1656             :                                ParameterMode mode = INTPTR_PARAMETERS);
    1657             : 
    1658             :   // Uses memset to effectively initialize the given FixedArray with zeroes.
    1659             :   void FillFixedArrayWithSmiZero(TNode<FixedArray> array,
    1660             :                                  TNode<IntPtrT> length);
    1661             :   void FillFixedDoubleArrayWithZero(TNode<FixedDoubleArray> array,
    1662             :                                     TNode<IntPtrT> length);
    1663             : 
    1664             :   void FillPropertyArrayWithUndefined(Node* array, Node* from_index,
    1665             :                                       Node* to_index,
    1666             :                                       ParameterMode mode = INTPTR_PARAMETERS);
    1667             : 
    1668             :   enum class DestroySource { kNo, kYes };
    1669             : 
    1670             :   // Specify DestroySource::kYes if {from_array} is being supplanted by
    1671             :   // {to_array}. This offers a slight performance benefit by simply copying the
    1672             :   // array word by word. The source may be destroyed at the end of this macro.
    1673             :   //
    1674             :   // Otherwise, specify DestroySource::kNo for operations where an Object is
    1675             :   // being cloned, to ensure that MutableHeapNumbers are unique between the
    1676             :   // source and cloned object.
    1677             :   void CopyPropertyArrayValues(Node* from_array, Node* to_array, Node* length,
    1678             :                                WriteBarrierMode barrier_mode,
    1679             :                                ParameterMode mode,
    1680             :                                DestroySource destroy_source);
    1681             : 
    1682             :   // Copies all elements from |from_array| of |length| size to
    1683             :   // |to_array| of the same size respecting the elements kind.
    1684         336 :   void CopyFixedArrayElements(
    1685             :       ElementsKind kind, Node* from_array, Node* to_array, Node* length,
    1686             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1687             :       ParameterMode mode = INTPTR_PARAMETERS) {
    1688         336 :     CopyFixedArrayElements(kind, from_array, kind, to_array,
    1689             :                            IntPtrOrSmiConstant(0, mode), length, length,
    1690         336 :                            barrier_mode, mode);
    1691         336 :   }
    1692             : 
    1693             :   // Copies |element_count| elements from |from_array| starting from element
    1694             :   // zero to |to_array| of |capacity| size respecting both array's elements
    1695             :   // kinds.
    1696        5636 :   void CopyFixedArrayElements(
    1697             :       ElementsKind from_kind, Node* from_array, ElementsKind to_kind,
    1698             :       Node* to_array, Node* element_count, Node* capacity,
    1699             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1700             :       ParameterMode mode = INTPTR_PARAMETERS) {
    1701        5636 :     CopyFixedArrayElements(from_kind, from_array, to_kind, to_array,
    1702             :                            IntPtrOrSmiConstant(0, mode), element_count,
    1703        5636 :                            capacity, barrier_mode, mode);
    1704        5636 :   }
    1705             : 
    1706             :   // Copies |element_count| elements from |from_array| starting from element
    1707             :   // |first_element| to |to_array| of |capacity| size respecting both array's
    1708             :   // elements kinds.
    1709             :   // |convert_holes| tells the function whether to convert holes to undefined.
    1710             :   // |var_holes_converted| can be used to signify that the conversion happened
    1711             :   // (i.e. that there were holes). If |convert_holes_to_undefined| is
    1712             :   // HoleConversionMode::kConvertToUndefined, then it must not be the case that
    1713             :   // IsDoubleElementsKind(to_kind).
    1714             :   void CopyFixedArrayElements(
    1715             :       ElementsKind from_kind, Node* from_array, ElementsKind to_kind,
    1716             :       Node* to_array, Node* first_element, Node* element_count, Node* capacity,
    1717             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    1718             :       ParameterMode mode = INTPTR_PARAMETERS,
    1719             :       HoleConversionMode convert_holes = HoleConversionMode::kDontConvert,
    1720             :       TVariable<BoolT>* var_holes_converted = nullptr);
    1721             : 
    1722             :   void CopyFixedArrayElements(
    1723             :       ElementsKind from_kind, TNode<FixedArrayBase> from_array,
    1724             :       ElementsKind to_kind, TNode<FixedArrayBase> to_array,
    1725             :       TNode<Smi> first_element, TNode<Smi> element_count, TNode<Smi> capacity,
    1726             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
    1727             :     CopyFixedArrayElements(from_kind, from_array, to_kind, to_array,
    1728             :                            first_element, element_count, capacity, barrier_mode,
    1729             :                            SMI_PARAMETERS);
    1730             :   }
    1731             : 
    1732             :   void JumpIfPointersFromHereAreInteresting(TNode<Object> object,
    1733             :                                             Label* interesting);
    1734             : 
    1735             :   // Efficiently copy elements within a single array. The regions
    1736             :   // [src_index, src_index + length) and [dst_index, dst_index + length)
    1737             :   // can be overlapping.
    1738             :   void MoveElements(ElementsKind kind, TNode<FixedArrayBase> elements,
    1739             :                     TNode<IntPtrT> dst_index, TNode<IntPtrT> src_index,
    1740             :                     TNode<IntPtrT> length);
    1741             : 
    1742             :   // Efficiently copy elements from one array to another. The ElementsKind
    1743             :   // needs to be the same. Copy from src_elements at
    1744             :   // [src_index, src_index + length) to dst_elements at
    1745             :   // [dst_index, dst_index + length).
    1746             :   // The function decides whether it can use memcpy. In case it cannot,
    1747             :   // |write_barrier| can help it to skip write barrier. SKIP_WRITE_BARRIER is
    1748             :   // only safe when copying to new space, or when copying to old space and the
    1749             :   // array does not contain object pointers.
    1750             :   void CopyElements(ElementsKind kind, TNode<FixedArrayBase> dst_elements,
    1751             :                     TNode<IntPtrT> dst_index,
    1752             :                     TNode<FixedArrayBase> src_elements,
    1753             :                     TNode<IntPtrT> src_index, TNode<IntPtrT> length,
    1754             :                     WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER);
    1755             : 
    1756             :   TNode<FixedArray> HeapObjectToFixedArray(TNode<HeapObject> base,
    1757             :                                            Label* cast_fail);
    1758             : 
    1759        1008 :   TNode<FixedDoubleArray> HeapObjectToFixedDoubleArray(TNode<HeapObject> base,
    1760             :                                                        Label* cast_fail) {
    1761        2016 :     GotoIf(
    1762        2016 :         WordNotEqual(LoadMap(base), LoadRoot(RootIndex::kFixedDoubleArrayMap)),
    1763        1008 :         cast_fail);
    1764        1008 :     return UncheckedCast<FixedDoubleArray>(base);
    1765             :   }
    1766             : 
    1767          56 :   TNode<SloppyArgumentsElements> HeapObjectToSloppyArgumentsElements(
    1768             :       TNode<HeapObject> base, Label* cast_fail) {
    1769         112 :     GotoIf(WordNotEqual(LoadMap(base),
    1770         112 :                         LoadRoot(RootIndex::kSloppyArgumentsElementsMap)),
    1771          56 :            cast_fail);
    1772          56 :     return UncheckedCast<SloppyArgumentsElements>(base);
    1773             :   }
    1774             : 
    1775          56 :   TNode<Int32T> ConvertElementsKindToInt(TNode<Int32T> elements_kind) {
    1776          56 :     return UncheckedCast<Int32T>(elements_kind);
    1777             :   }
    1778             : 
    1779             :   enum class ExtractFixedArrayFlag {
    1780             :     kFixedArrays = 1,
    1781             :     kFixedDoubleArrays = 2,
    1782             :     kDontCopyCOW = 4,
    1783             :     kNewSpaceAllocationOnly = 8,
    1784             :     kAllFixedArrays = kFixedArrays | kFixedDoubleArrays,
    1785             :     kAllFixedArraysDontCopyCOW = kAllFixedArrays | kDontCopyCOW
    1786             :   };
    1787             : 
    1788             :   typedef base::Flags<ExtractFixedArrayFlag> ExtractFixedArrayFlags;
    1789             : 
    1790             :   // Copy a portion of an existing FixedArray or FixedDoubleArray into a new
    1791             :   // array, including special appropriate handling for empty arrays and COW
    1792             :   // arrays. The result array will be of the same type as the original array.
    1793             :   //
    1794             :   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
    1795             :   // elements.
    1796             :   // * |first| is the starting element index to copy from, if nullptr is passed
    1797             :   // then index zero is used by default.
    1798             :   // * |count| is the number of elements to copy out of the source array
    1799             :   // starting from and including the element indexed by |start|. If |count| is
    1800             :   // nullptr, then all of the elements from |start| to the end of |source| are
    1801             :   // copied.
    1802             :   // * |capacity| determines the size of the allocated result array, with
    1803             :   // |capacity| >= |count|. If |capacity| is nullptr, then |count| is used as
    1804             :   // the destination array's capacity.
    1805             :   // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both
    1806             :   // are detected and copied. Although it's always correct to pass
    1807             :   // kAllFixedArrays, the generated code is more compact and efficient if the
    1808             :   // caller can specify whether only FixedArrays or FixedDoubleArrays will be
    1809             :   // passed as the |source| parameter.
    1810             :   // * |parameter_mode| determines the parameter mode of |first|, |count| and
    1811             :   // |capacity|.
    1812             :   // * If |var_holes_converted| is given, any holes will be converted to
    1813             :   // undefined and the variable will be set according to whether or not there
    1814             :   // were any hole.
    1815             :   // * If |source_elements_kind| is given, the function will try to use the
    1816             :   // runtime elements kind of source to make copy faster. More specifically, it
    1817             :   // can skip write barriers.
    1818             :   TNode<FixedArrayBase> ExtractFixedArray(
    1819             :       Node* source, Node* first, Node* count = nullptr,
    1820             :       Node* capacity = nullptr,
    1821             :       ExtractFixedArrayFlags extract_flags =
    1822             :           ExtractFixedArrayFlag::kAllFixedArrays,
    1823             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1824             :       TVariable<BoolT>* var_holes_converted = nullptr,
    1825             :       Node* source_elements_kind = nullptr);
    1826             : 
    1827         560 :   TNode<FixedArrayBase> ExtractFixedArray(
    1828             :       TNode<FixedArrayBase> source, TNode<Smi> first, TNode<Smi> count,
    1829             :       TNode<Smi> capacity,
    1830             :       ExtractFixedArrayFlags extract_flags =
    1831             :           ExtractFixedArrayFlag::kAllFixedArrays) {
    1832             :     return ExtractFixedArray(source, first, count, capacity, extract_flags,
    1833         560 :                              SMI_PARAMETERS);
    1834             :   }
    1835             : 
    1836             :   // Copy a portion of an existing FixedArray or FixedDoubleArray into a new
    1837             :   // FixedArray, including special appropriate handling for COW arrays.
    1838             :   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
    1839             :   // elements. |source| is assumed to be non-empty.
    1840             :   // * |first| is the starting element index to copy from.
    1841             :   // * |count| is the number of elements to copy out of the source array
    1842             :   // starting from and including the element indexed by |start|.
    1843             :   // * |capacity| determines the size of the allocated result array, with
    1844             :   // |capacity| >= |count|.
    1845             :   // * |source_map| is the map of the |source|.
    1846             :   // * |from_kind| is the elements kind that is consistent with |source| being
    1847             :   // a FixedArray or FixedDoubleArray. This function only cares about double vs.
    1848             :   // non-double, so as to distinguish FixedDoubleArray vs. FixedArray. It does
    1849             :   // not care about holeyness. For example, when |source| is a FixedArray,
    1850             :   // PACKED/HOLEY_ELEMENTS can be used, but not PACKED_DOUBLE_ELEMENTS.
    1851             :   // * |allocation_flags| and |extract_flags| influence how the target
    1852             :   // FixedArray is allocated.
    1853             :   // * |parameter_mode| determines the parameter mode of |first|, |count| and
    1854             :   // |capacity|.
    1855             :   // * |convert_holes| is used to signify that the target array should use
    1856             :   // undefined in places of holes.
    1857             :   // * If |convert_holes| is true and |var_holes_converted| not nullptr, then
    1858             :   // |var_holes_converted| is used to signal whether any holes were found and
    1859             :   // converted. The caller should use this information to decide which map is
    1860             :   // compatible with the result array. For example, if the input was of
    1861             :   // HOLEY_SMI_ELEMENTS kind, and a conversion took place, the result will be
    1862             :   // compatible only with HOLEY_ELEMENTS and PACKED_ELEMENTS.
    1863             :   TNode<FixedArray> ExtractToFixedArray(
    1864             :       Node* source, Node* first, Node* count, Node* capacity, Node* source_map,
    1865             :       ElementsKind from_kind = PACKED_ELEMENTS,
    1866             :       AllocationFlags allocation_flags = AllocationFlag::kNone,
    1867             :       ExtractFixedArrayFlags extract_flags =
    1868             :           ExtractFixedArrayFlag::kAllFixedArrays,
    1869             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
    1870             :       HoleConversionMode convert_holes = HoleConversionMode::kDontConvert,
    1871             :       TVariable<BoolT>* var_holes_converted = nullptr,
    1872             :       Node* source_runtime_kind = nullptr);
    1873             : 
    1874             :   // Attempt to copy a FixedDoubleArray to another FixedDoubleArray. In the case
    1875             :   // where the source array has a hole, produce a FixedArray instead where holes
    1876             :   // are replaced with undefined.
    1877             :   // * |source| is a FixedDoubleArray from which to copy elements.
    1878             :   // * |first| is the starting element index to copy from.
    1879             :   // * |count| is the number of elements to copy out of the source array
    1880             :   // starting from and including the element indexed by |start|.
    1881             :   // * |capacity| determines the size of the allocated result array, with
    1882             :   // |capacity| >= |count|.
    1883             :   // * |source_map| is the map of |source|. It will be used as the map of the
    1884             :   // target array if the target can stay a FixedDoubleArray. Otherwise if the
    1885             :   // target array needs to be a FixedArray, the FixedArrayMap will be used.
    1886             :   // * |var_holes_converted| is used to signal whether a FixedAray
    1887             :   // is produced or not.
    1888             :   // * |allocation_flags| and |extract_flags| influence how the target array is
    1889             :   // allocated.
    1890             :   // * |parameter_mode| determines the parameter mode of |first|, |count| and
    1891             :   // |capacity|.
    1892             :   TNode<FixedArrayBase> ExtractFixedDoubleArrayFillingHoles(
    1893             :       Node* source, Node* first, Node* count, Node* capacity, Node* source_map,
    1894             :       TVariable<BoolT>* var_holes_converted, AllocationFlags allocation_flags,
    1895             :       ExtractFixedArrayFlags extract_flags =
    1896             :           ExtractFixedArrayFlag::kAllFixedArrays,
    1897             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    1898             : 
    1899             :   // Copy the entire contents of a FixedArray or FixedDoubleArray to a new
    1900             :   // array, including special appropriate handling for empty arrays and COW
    1901             :   // arrays.
    1902             :   //
    1903             :   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
    1904             :   // elements.
    1905             :   // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both
    1906             :   // are detected and copied. Although it's always correct to pass
    1907             :   // kAllFixedArrays, the generated code is more compact and efficient if the
    1908             :   // caller can specify whether only FixedArrays or FixedDoubleArrays will be
    1909             :   // passed as the |source| parameter.
    1910         348 :   Node* CloneFixedArray(Node* source,
    1911             :                         ExtractFixedArrayFlags flags =
    1912             :                             ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW) {
    1913         336 :     ParameterMode mode = OptimalParameterMode();
    1914         696 :     return ExtractFixedArray(source, IntPtrOrSmiConstant(0, mode), nullptr,
    1915        1032 :                              nullptr, flags, mode);
    1916             :   }
    1917             : 
    1918             :   // Copies |character_count| elements from |from_string| to |to_string|
    1919             :   // starting at the |from_index|'th character. |from_string| and |to_string|
    1920             :   // can either be one-byte strings or two-byte strings, although if
    1921             :   // |from_string| is two-byte, then |to_string| must be two-byte.
    1922             :   // |from_index|, |to_index| and |character_count| must be intptr_ts s.t. 0 <=
    1923             :   // |from_index| <= |from_index| + |character_count| <= from_string.length and
    1924             :   // 0 <= |to_index| <= |to_index| + |character_count| <= to_string.length.
    1925             :   void CopyStringCharacters(Node* from_string, Node* to_string,
    1926             :                             TNode<IntPtrT> from_index, TNode<IntPtrT> to_index,
    1927             :                             TNode<IntPtrT> character_count,
    1928             :                             String::Encoding from_encoding,
    1929             :                             String::Encoding to_encoding);
    1930             : 
    1931             :   // Loads an element from |array| of |from_kind| elements by given |offset|
    1932             :   // (NOTE: not index!), does a hole check if |if_hole| is provided and
    1933             :   // converts the value so that it becomes ready for storing to array of
    1934             :   // |to_kind| elements.
    1935             :   Node* LoadElementAndPrepareForStore(Node* array, Node* offset,
    1936             :                                       ElementsKind from_kind,
    1937             :                                       ElementsKind to_kind, Label* if_hole);
    1938             : 
    1939             :   Node* CalculateNewElementsCapacity(Node* old_capacity,
    1940             :                                      ParameterMode mode = INTPTR_PARAMETERS);
    1941             : 
    1942         112 :   TNode<Smi> CalculateNewElementsCapacity(TNode<Smi> old_capacity) {
    1943         112 :     return CAST(CalculateNewElementsCapacity(old_capacity, SMI_PARAMETERS));
    1944             :   }
    1945             : 
    1946             :   // Tries to grow the |elements| array of given |object| to store the |key|
    1947             :   // or bails out if the growing gap is too big. Returns new elements.
    1948             :   Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind,
    1949             :                                 Node* key, Label* bailout);
    1950             : 
    1951             :   // Tries to grow the |capacity|-length |elements| array of given |object|
    1952             :   // to store the |key| or bails out if the growing gap is too big. Returns
    1953             :   // new elements.
    1954             :   Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind,
    1955             :                                 Node* key, Node* capacity, ParameterMode mode,
    1956             :                                 Label* bailout);
    1957             : 
    1958             :   // Grows elements capacity of given object. Returns new elements.
    1959             :   Node* GrowElementsCapacity(Node* object, Node* elements,
    1960             :                              ElementsKind from_kind, ElementsKind to_kind,
    1961             :                              Node* capacity, Node* new_capacity,
    1962             :                              ParameterMode mode, Label* bailout);
    1963             : 
    1964             :   // Given a need to grow by |growth|, allocate an appropriate new capacity
    1965             :   // if necessary, and return a new elements FixedArray object. Label |bailout|
    1966             :   // is followed for allocation failure.
    1967             :   void PossiblyGrowElementsCapacity(ParameterMode mode, ElementsKind kind,
    1968             :                                     Node* array, Node* length,
    1969             :                                     Variable* var_elements, Node* growth,
    1970             :                                     Label* bailout);
    1971             : 
    1972             :   // Allocation site manipulation
    1973             :   void InitializeAllocationMemento(Node* base_allocation,
    1974             :                                    Node* base_allocation_size,
    1975             :                                    Node* allocation_site);
    1976             : 
    1977             :   Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber);
    1978             :   Node* TruncateTaggedToFloat64(Node* context, Node* value);
    1979             :   Node* TruncateTaggedToWord32(Node* context, Node* value);
    1980             :   void TaggedToWord32OrBigInt(Node* context, Node* value, Label* if_number,
    1981             :                               Variable* var_word32, Label* if_bigint,
    1982             :                               Variable* var_bigint);
    1983             :   void TaggedToWord32OrBigIntWithFeedback(
    1984             :       Node* context, Node* value, Label* if_number, Variable* var_word32,
    1985             :       Label* if_bigint, Variable* var_bigint, Variable* var_feedback);
    1986             : 
    1987             :   // Truncate the floating point value of a HeapNumber to an Int32.
    1988             :   Node* TruncateHeapNumberValueToWord32(Node* object);
    1989             : 
    1990             :   // Conversions.
    1991             :   void TryHeapNumberToSmi(TNode<HeapNumber> number, TVariable<Smi>& output,
    1992             :                           Label* if_smi);
    1993             :   void TryFloat64ToSmi(TNode<Float64T> number, TVariable<Smi>& output,
    1994             :                        Label* if_smi);
    1995             :   TNode<Number> ChangeFloat64ToTagged(SloppyTNode<Float64T> value);
    1996             :   TNode<Number> ChangeInt32ToTagged(SloppyTNode<Int32T> value);
    1997             :   TNode<Number> ChangeUint32ToTagged(SloppyTNode<Uint32T> value);
    1998             :   TNode<Number> ChangeUintPtrToTagged(TNode<UintPtrT> value);
    1999             :   TNode<Uint32T> ChangeNumberToUint32(TNode<Number> value);
    2000             :   TNode<Float64T> ChangeNumberToFloat64(SloppyTNode<Number> value);
    2001             :   TNode<UintPtrT> TryNumberToUintPtr(TNode<Number> value, Label* if_negative);
    2002         280 :   TNode<UintPtrT> ChangeNonnegativeNumberToUintPtr(TNode<Number> value) {
    2003         280 :     return TryNumberToUintPtr(value, nullptr);
    2004             :   }
    2005             : 
    2006             :   void TaggedToNumeric(Node* context, Node* value, Label* done,
    2007             :                        Variable* var_numeric);
    2008             :   void TaggedToNumericWithFeedback(Node* context, Node* value, Label* done,
    2009             :                                    Variable* var_numeric,
    2010             :                                    Variable* var_feedback);
    2011             : 
    2012             :   TNode<WordT> TimesSystemPointerSize(SloppyTNode<WordT> value);
    2013         448 :   TNode<IntPtrT> TimesSystemPointerSize(TNode<IntPtrT> value) {
    2014         896 :     return Signed(TimesSystemPointerSize(implicit_cast<TNode<WordT>>(value)));
    2015             :   }
    2016             :   TNode<UintPtrT> TimesSystemPointerSize(TNode<UintPtrT> value) {
    2017             :     return Unsigned(TimesSystemPointerSize(implicit_cast<TNode<WordT>>(value)));
    2018             :   }
    2019             : 
    2020             :   TNode<WordT> TimesTaggedSize(SloppyTNode<WordT> value);
    2021        5912 :   TNode<IntPtrT> TimesTaggedSize(TNode<IntPtrT> value) {
    2022       11824 :     return Signed(TimesTaggedSize(implicit_cast<TNode<WordT>>(value)));
    2023             :   }
    2024         504 :   TNode<UintPtrT> TimesTaggedSize(TNode<UintPtrT> value) {
    2025        1008 :     return Unsigned(TimesTaggedSize(implicit_cast<TNode<WordT>>(value)));
    2026             :   }
    2027             : 
    2028             :   TNode<WordT> TimesDoubleSize(SloppyTNode<WordT> value);
    2029             :   TNode<UintPtrT> TimesDoubleSize(TNode<UintPtrT> value) {
    2030             :     return Unsigned(TimesDoubleSize(implicit_cast<TNode<WordT>>(value)));
    2031             :   }
    2032          56 :   TNode<IntPtrT> TimesDoubleSize(TNode<IntPtrT> value) {
    2033         112 :     return Signed(TimesDoubleSize(implicit_cast<TNode<WordT>>(value)));
    2034             :   }
    2035             : 
    2036             :   // Type conversions.
    2037             :   // Throws a TypeError for {method_name} if {value} is not coercible to Object,
    2038             :   // or returns the {value} converted to a String otherwise.
    2039             :   TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
    2040             :                              TNode<String> method_name);
    2041         784 :   TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
    2042             :                              char const* method_name) {
    2043         784 :     return ToThisString(context, value, StringConstant(method_name));
    2044             :   }
    2045             : 
    2046             :   // Throws a TypeError for {method_name} if {value} is neither of the given
    2047             :   // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or
    2048             :   // returns the {value} (or wrapped value) otherwise.
    2049             :   Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type,
    2050             :                     char const* method_name);
    2051             : 
    2052             :   // Throws a TypeError for {method_name} if {value} is not of the given
    2053             :   // instance type. Returns {value}'s map.
    2054             :   Node* ThrowIfNotInstanceType(Node* context, Node* value,
    2055             :                                InstanceType instance_type,
    2056             :                                char const* method_name);
    2057             :   // Throws a TypeError for {method_name} if {value} is not a JSReceiver.
    2058             :   // Returns the {value}'s map.
    2059             :   Node* ThrowIfNotJSReceiver(Node* context, Node* value,
    2060             :                              MessageTemplate msg_template,
    2061             :                              const char* method_name = nullptr);
    2062             : 
    2063             :   void ThrowRangeError(Node* context, MessageTemplate message,
    2064             :                        Node* arg0 = nullptr, Node* arg1 = nullptr,
    2065             :                        Node* arg2 = nullptr);
    2066             :   void ThrowTypeError(Node* context, MessageTemplate message,
    2067             :                       char const* arg0 = nullptr, char const* arg1 = nullptr);
    2068             :   void ThrowTypeError(Node* context, MessageTemplate message, Node* arg0,
    2069             :                       Node* arg1 = nullptr, Node* arg2 = nullptr);
    2070             : 
    2071             :   // Type checks.
    2072             :   // Check whether the map is for an object with special properties, such as a
    2073             :   // JSProxy or an object with interceptors.
    2074             :   TNode<BoolT> InstanceTypeEqual(SloppyTNode<Int32T> instance_type, int type);
    2075             :   TNode<BoolT> IsAccessorInfo(SloppyTNode<HeapObject> object);
    2076             :   TNode<BoolT> IsAccessorPair(SloppyTNode<HeapObject> object);
    2077             :   TNode<BoolT> IsAllocationSite(SloppyTNode<HeapObject> object);
    2078             :   TNode<BoolT> IsAnyHeapNumber(SloppyTNode<HeapObject> object);
    2079             :   TNode<BoolT> IsNoElementsProtectorCellInvalid();
    2080             :   TNode<BoolT> IsArrayIteratorProtectorCellInvalid();
    2081             :   TNode<BoolT> IsBigIntInstanceType(SloppyTNode<Int32T> instance_type);
    2082             :   TNode<BoolT> IsBigInt(SloppyTNode<HeapObject> object);
    2083             :   TNode<BoolT> IsBoolean(SloppyTNode<HeapObject> object);
    2084             :   TNode<BoolT> IsCallableMap(SloppyTNode<Map> map);
    2085             :   TNode<BoolT> IsCallable(SloppyTNode<HeapObject> object);
    2086             :   TNode<BoolT> TaggedIsCallable(TNode<Object> object);
    2087             :   TNode<BoolT> IsCell(SloppyTNode<HeapObject> object);
    2088             :   TNode<BoolT> IsCode(SloppyTNode<HeapObject> object);
    2089             :   TNode<BoolT> IsConsStringInstanceType(SloppyTNode<Int32T> instance_type);
    2090             :   TNode<BoolT> IsConstructorMap(SloppyTNode<Map> map);
    2091             :   TNode<BoolT> IsConstructor(SloppyTNode<HeapObject> object);
    2092             :   TNode<BoolT> IsDeprecatedMap(SloppyTNode<Map> map);
    2093             :   TNode<BoolT> IsNameDictionary(SloppyTNode<HeapObject> object);
    2094             :   TNode<BoolT> IsGlobalDictionary(SloppyTNode<HeapObject> object);
    2095             :   TNode<BoolT> IsExtensibleMap(SloppyTNode<Map> map);
    2096             :   TNode<BoolT> IsExtensibleNonPrototypeMap(TNode<Map> map);
    2097             :   TNode<BoolT> IsExternalStringInstanceType(SloppyTNode<Int32T> instance_type);
    2098             :   TNode<BoolT> IsFeedbackCell(SloppyTNode<HeapObject> object);
    2099             :   TNode<BoolT> IsFeedbackVector(SloppyTNode<HeapObject> object);
    2100             :   TNode<BoolT> IsContext(SloppyTNode<HeapObject> object);
    2101             :   TNode<BoolT> IsFixedArray(SloppyTNode<HeapObject> object);
    2102             :   TNode<BoolT> IsFixedArraySubclass(SloppyTNode<HeapObject> object);
    2103             :   TNode<BoolT> IsFixedArrayWithKind(SloppyTNode<HeapObject> object,
    2104             :                                     ElementsKind kind);
    2105             :   TNode<BoolT> IsFixedArrayWithKindOrEmpty(SloppyTNode<HeapObject> object,
    2106             :                                            ElementsKind kind);
    2107             :   TNode<BoolT> IsFixedDoubleArray(SloppyTNode<HeapObject> object);
    2108             :   TNode<BoolT> IsFixedTypedArray(SloppyTNode<HeapObject> object);
    2109             :   TNode<BoolT> IsFunctionWithPrototypeSlotMap(SloppyTNode<Map> map);
    2110             :   TNode<BoolT> IsHashTable(SloppyTNode<HeapObject> object);
    2111             :   TNode<BoolT> IsEphemeronHashTable(SloppyTNode<HeapObject> object);
    2112             :   TNode<BoolT> IsHeapNumber(SloppyTNode<HeapObject> object);
    2113             :   TNode<BoolT> IsHeapNumberInstanceType(SloppyTNode<Int32T> instance_type);
    2114             :   TNode<BoolT> IsOddball(SloppyTNode<HeapObject> object);
    2115             :   TNode<BoolT> IsOddballInstanceType(SloppyTNode<Int32T> instance_type);
    2116             :   TNode<BoolT> IsIndirectStringInstanceType(SloppyTNode<Int32T> instance_type);
    2117             :   TNode<BoolT> IsJSArrayBuffer(SloppyTNode<HeapObject> object);
    2118             :   TNode<BoolT> IsJSDataView(TNode<HeapObject> object);
    2119             :   TNode<BoolT> IsJSArrayInstanceType(SloppyTNode<Int32T> instance_type);
    2120             :   TNode<BoolT> IsJSArrayMap(SloppyTNode<Map> map);
    2121             :   TNode<BoolT> IsJSArray(SloppyTNode<HeapObject> object);
    2122             :   TNode<BoolT> IsJSArrayIterator(SloppyTNode<HeapObject> object);
    2123             :   TNode<BoolT> IsJSAsyncGeneratorObject(SloppyTNode<HeapObject> object);
    2124             :   TNode<BoolT> IsJSFunctionInstanceType(SloppyTNode<Int32T> instance_type);
    2125             :   TNode<BoolT> IsAllocationSiteInstanceType(SloppyTNode<Int32T> instance_type);
    2126             :   TNode<BoolT> IsJSFunctionMap(SloppyTNode<Map> map);
    2127             :   TNode<BoolT> IsJSFunction(SloppyTNode<HeapObject> object);
    2128             :   TNode<BoolT> IsJSGeneratorObject(SloppyTNode<HeapObject> object);
    2129             :   TNode<BoolT> IsJSGlobalProxyInstanceType(SloppyTNode<Int32T> instance_type);
    2130             :   TNode<BoolT> IsJSGlobalProxy(SloppyTNode<HeapObject> object);
    2131             :   TNode<BoolT> IsJSObjectInstanceType(SloppyTNode<Int32T> instance_type);
    2132             :   TNode<BoolT> IsJSObjectMap(SloppyTNode<Map> map);
    2133             :   TNode<BoolT> IsJSObject(SloppyTNode<HeapObject> object);
    2134             :   TNode<BoolT> IsJSPromiseMap(SloppyTNode<Map> map);
    2135             :   TNode<BoolT> IsJSPromise(SloppyTNode<HeapObject> object);
    2136             :   TNode<BoolT> IsJSProxy(SloppyTNode<HeapObject> object);
    2137             :   TNode<BoolT> IsJSReceiverInstanceType(SloppyTNode<Int32T> instance_type);
    2138             :   TNode<BoolT> IsJSReceiverMap(SloppyTNode<Map> map);
    2139             :   TNode<BoolT> IsJSReceiver(SloppyTNode<HeapObject> object);
    2140             :   TNode<BoolT> IsJSRegExp(SloppyTNode<HeapObject> object);
    2141             :   TNode<BoolT> IsJSTypedArray(SloppyTNode<HeapObject> object);
    2142             :   TNode<BoolT> IsJSValueInstanceType(SloppyTNode<Int32T> instance_type);
    2143             :   TNode<BoolT> IsJSValueMap(SloppyTNode<Map> map);
    2144             :   TNode<BoolT> IsJSValue(SloppyTNode<HeapObject> object);
    2145             :   TNode<BoolT> IsMap(SloppyTNode<HeapObject> object);
    2146             :   TNode<BoolT> IsMutableHeapNumber(SloppyTNode<HeapObject> object);
    2147             :   TNode<BoolT> IsName(SloppyTNode<HeapObject> object);
    2148             :   TNode<BoolT> IsNameInstanceType(SloppyTNode<Int32T> instance_type);
    2149             :   TNode<BoolT> IsNativeContext(SloppyTNode<HeapObject> object);
    2150             :   TNode<BoolT> IsNullOrJSReceiver(SloppyTNode<HeapObject> object);
    2151             :   TNode<BoolT> IsNullOrUndefined(SloppyTNode<Object> object);
    2152             :   TNode<BoolT> IsNumberDictionary(SloppyTNode<HeapObject> object);
    2153             :   TNode<BoolT> IsOneByteStringInstanceType(SloppyTNode<Int32T> instance_type);
    2154             :   TNode<BoolT> IsPrimitiveInstanceType(SloppyTNode<Int32T> instance_type);
    2155             :   TNode<BoolT> IsPrivateSymbol(SloppyTNode<HeapObject> object);
    2156             :   TNode<BoolT> IsPromiseCapability(SloppyTNode<HeapObject> object);
    2157             :   TNode<BoolT> IsPropertyArray(SloppyTNode<HeapObject> object);
    2158             :   TNode<BoolT> IsPropertyCell(SloppyTNode<HeapObject> object);
    2159             :   TNode<BoolT> IsPrototypeInitialArrayPrototype(SloppyTNode<Context> context,
    2160             :                                                 SloppyTNode<Map> map);
    2161             :   TNode<BoolT> IsPrototypeTypedArrayPrototype(SloppyTNode<Context> context,
    2162             :                                               SloppyTNode<Map> map);
    2163             : 
    2164             :   TNode<BoolT> IsFastAliasedArgumentsMap(TNode<Context> context,
    2165             :                                          TNode<Map> map);
    2166             :   TNode<BoolT> IsSlowAliasedArgumentsMap(TNode<Context> context,
    2167             :                                          TNode<Map> map);
    2168             :   TNode<BoolT> IsSloppyArgumentsMap(TNode<Context> context, TNode<Map> map);
    2169             :   TNode<BoolT> IsStrictArgumentsMap(TNode<Context> context, TNode<Map> map);
    2170             : 
    2171             :   TNode<BoolT> IsSequentialStringInstanceType(
    2172             :       SloppyTNode<Int32T> instance_type);
    2173             :   TNode<BoolT> IsUncachedExternalStringInstanceType(
    2174             :       SloppyTNode<Int32T> instance_type);
    2175             :   TNode<BoolT> IsSpecialReceiverInstanceType(TNode<Int32T> instance_type);
    2176             :   TNode<BoolT> IsCustomElementsReceiverInstanceType(
    2177             :       TNode<Int32T> instance_type);
    2178             :   TNode<BoolT> IsSpecialReceiverMap(SloppyTNode<Map> map);
    2179             :   // Returns true if the map corresponds to non-special fast or dictionary
    2180             :   // object.
    2181             :   TNode<BoolT> IsSimpleObjectMap(TNode<Map> map);
    2182             :   TNode<BoolT> IsStringInstanceType(SloppyTNode<Int32T> instance_type);
    2183             :   TNode<BoolT> IsString(SloppyTNode<HeapObject> object);
    2184             :   TNode<BoolT> IsSymbolInstanceType(SloppyTNode<Int32T> instance_type);
    2185             :   TNode<BoolT> IsSymbol(SloppyTNode<HeapObject> object);
    2186             :   TNode<BoolT> IsInternalizedStringInstanceType(TNode<Int32T> instance_type);
    2187             :   TNode<BoolT> IsUniqueName(TNode<HeapObject> object);
    2188             :   TNode<BoolT> IsUniqueNameNoIndex(TNode<HeapObject> object);
    2189             :   TNode<BoolT> IsUndetectableMap(SloppyTNode<Map> map);
    2190             :   TNode<BoolT> IsNotWeakFixedArraySubclass(SloppyTNode<HeapObject> object);
    2191             :   TNode<BoolT> IsZeroOrContext(SloppyTNode<Object> object);
    2192             : 
    2193             :   inline Node* IsSharedFunctionInfo(Node* object) {
    2194             :     return IsSharedFunctionInfoMap(LoadMap(object));
    2195             :   }
    2196             : 
    2197             :   TNode<BoolT> IsPromiseResolveProtectorCellInvalid();
    2198             :   TNode<BoolT> IsPromiseThenProtectorCellInvalid();
    2199             :   TNode<BoolT> IsArraySpeciesProtectorCellInvalid();
    2200             :   TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid();
    2201             :   TNode<BoolT> IsRegExpSpeciesProtectorCellInvalid();
    2202             :   TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid();
    2203             : 
    2204             :   TNode<BoolT> IsMockArrayBufferAllocatorFlag() {
    2205             :     TNode<Word32T> flag_value = UncheckedCast<Word32T>(Load(
    2206             :         MachineType::Uint8(),
    2207             :         ExternalConstant(
    2208             :             ExternalReference::address_of_mock_arraybuffer_allocator_flag())));
    2209             :     return Word32NotEqual(Word32And(flag_value, Int32Constant(0xFF)),
    2210             :                           Int32Constant(0));
    2211             :   }
    2212             : 
    2213             :   // True iff |object| is a Smi or a HeapNumber.
    2214             :   TNode<BoolT> IsNumber(SloppyTNode<Object> object);
    2215             :   // True iff |object| is a Smi or a HeapNumber or a BigInt.
    2216             :   TNode<BoolT> IsNumeric(SloppyTNode<Object> object);
    2217             : 
    2218             :   // True iff |number| is either a Smi, or a HeapNumber whose value is not
    2219             :   // within Smi range.
    2220             :   TNode<BoolT> IsNumberNormalized(SloppyTNode<Number> number);
    2221             :   TNode<BoolT> IsNumberPositive(SloppyTNode<Number> number);
    2222             :   TNode<BoolT> IsHeapNumberPositive(TNode<HeapNumber> number);
    2223             : 
    2224             :   // True iff {number} is non-negative and less or equal than 2**53-1.
    2225             :   TNode<BoolT> IsNumberNonNegativeSafeInteger(TNode<Number> number);
    2226             : 
    2227             :   // True iff {number} represents an integer value.
    2228             :   TNode<BoolT> IsInteger(TNode<Object> number);
    2229             :   TNode<BoolT> IsInteger(TNode<HeapNumber> number);
    2230             : 
    2231             :   // True iff abs({number}) <= 2**53 -1
    2232             :   TNode<BoolT> IsSafeInteger(TNode<Object> number);
    2233             :   TNode<BoolT> IsSafeInteger(TNode<HeapNumber> number);
    2234             : 
    2235             :   // True iff {number} represents a valid uint32t value.
    2236             :   TNode<BoolT> IsHeapNumberUint32(TNode<HeapNumber> number);
    2237             : 
    2238             :   // True iff {number} is a positive number and a valid array index in the range
    2239             :   // [0, 2^32-1).
    2240             :   TNode<BoolT> IsNumberArrayIndex(TNode<Number> number);
    2241             : 
    2242             :   Node* FixedArraySizeDoesntFitInNewSpace(
    2243             :       Node* element_count, int base_size = FixedArray::kHeaderSize,
    2244             :       ParameterMode mode = INTPTR_PARAMETERS);
    2245             : 
    2246             :   // ElementsKind helpers:
    2247        8120 :   TNode<BoolT> ElementsKindEqual(TNode<Int32T> a, TNode<Int32T> b) {
    2248        8120 :     return Word32Equal(a, b);
    2249             :   }
    2250       18816 :   bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
    2251             :   Node* IsFastElementsKind(Node* elements_kind);
    2252           0 :   bool IsFastElementsKind(ElementsKind kind) {
    2253           0 :     return v8::internal::IsFastElementsKind(kind);
    2254             :   }
    2255             :   TNode<BoolT> IsDictionaryElementsKind(TNode<Int32T> elements_kind) {
    2256             :     return ElementsKindEqual(elements_kind, Int32Constant(DICTIONARY_ELEMENTS));
    2257             :   }
    2258             :   TNode<BoolT> IsDoubleElementsKind(TNode<Int32T> elements_kind);
    2259      141328 :   bool IsDoubleElementsKind(ElementsKind kind) {
    2260      141328 :     return v8::internal::IsDoubleElementsKind(kind);
    2261             :   }
    2262             :   Node* IsFastSmiOrTaggedElementsKind(Node* elements_kind);
    2263             :   Node* IsFastSmiElementsKind(Node* elements_kind);
    2264             :   Node* IsHoleyFastElementsKind(Node* elements_kind);
    2265             :   Node* IsElementsKindGreaterThan(Node* target_kind,
    2266             :                                   ElementsKind reference_kind);
    2267             :   TNode<BoolT> IsElementsKindLessThanOrEqual(TNode<Int32T> target_kind,
    2268             :                                              ElementsKind reference_kind);
    2269             : 
    2270             :   // String helpers.
    2271             :   // Load a character from a String (might flatten a ConsString).
    2272             :   TNode<Int32T> StringCharCodeAt(SloppyTNode<String> string,
    2273             :                                  SloppyTNode<IntPtrT> index);
    2274             :   // Return the single character string with only {code}.
    2275             :   TNode<String> StringFromSingleCharCode(TNode<Int32T> code);
    2276             : 
    2277             :   // Return a new string object which holds a substring containing the range
    2278             :   // [from,to[ of string.
    2279             :   TNode<String> SubString(TNode<String> string, TNode<IntPtrT> from,
    2280             :                           TNode<IntPtrT> to);
    2281             : 
    2282             :   // Return a new string object produced by concatenating |first| with |second|.
    2283             :   TNode<String> StringAdd(Node* context, TNode<String> first,
    2284             :                           TNode<String> second,
    2285             :                           Variable* var_feedback = nullptr);
    2286             : 
    2287             :   // Check if |string| is an indirect (thin or flat cons) string type that can
    2288             :   // be dereferenced by DerefIndirectString.
    2289             :   void BranchIfCanDerefIndirectString(Node* string, Node* instance_type,
    2290             :                                       Label* can_deref, Label* cannot_deref);
    2291             :   // Unpack an indirect (thin or flat cons) string type.
    2292             :   void DerefIndirectString(Variable* var_string, Node* instance_type);
    2293             :   // Check if |var_string| has an indirect (thin or flat cons) string type,
    2294             :   // and unpack it if so.
    2295             :   void MaybeDerefIndirectString(Variable* var_string, Node* instance_type,
    2296             :                                 Label* did_deref, Label* cannot_deref);
    2297             :   // Check if |var_left| or |var_right| has an indirect (thin or flat cons)
    2298             :   // string type, and unpack it/them if so. Fall through if nothing was done.
    2299             :   void MaybeDerefIndirectStrings(Variable* var_left, Node* left_instance_type,
    2300             :                                  Variable* var_right, Node* right_instance_type,
    2301             :                                  Label* did_something);
    2302             :   Node* DerefIndirectString(TNode<String> string, TNode<Int32T> instance_type,
    2303             :                             Label* cannot_deref);
    2304             : 
    2305             :   TNode<String> StringFromSingleCodePoint(TNode<Int32T> codepoint,
    2306             :                                           UnicodeEncoding encoding);
    2307             : 
    2308             :   // Type conversion helpers.
    2309             :   enum class BigIntHandling { kConvertToNumber, kThrow };
    2310             :   // Convert a String to a Number.
    2311             :   TNode<Number> StringToNumber(TNode<String> input);
    2312             :   // Convert a Number to a String.
    2313             :   TNode<String> NumberToString(TNode<Number> input);
    2314             :   // Convert a Non-Number object to a Number.
    2315             :   TNode<Number> NonNumberToNumber(
    2316             :       SloppyTNode<Context> context, SloppyTNode<HeapObject> input,
    2317             :       BigIntHandling bigint_handling = BigIntHandling::kThrow);
    2318             :   // Convert a Non-Number object to a Numeric.
    2319             :   TNode<Numeric> NonNumberToNumeric(SloppyTNode<Context> context,
    2320             :                                     SloppyTNode<HeapObject> input);
    2321             :   // Convert any object to a Number.
    2322             :   // Conforms to ES#sec-tonumber if {bigint_handling} == kThrow.
    2323             :   // With {bigint_handling} == kConvertToNumber, matches behavior of
    2324             :   // tc39.github.io/proposal-bigint/#sec-number-constructor-number-value.
    2325             :   TNode<Number> ToNumber(
    2326             :       SloppyTNode<Context> context, SloppyTNode<Object> input,
    2327             :       BigIntHandling bigint_handling = BigIntHandling::kThrow);
    2328             :   TNode<Number> ToNumber_Inline(SloppyTNode<Context> context,
    2329             :                                 SloppyTNode<Object> input);
    2330             : 
    2331             :   // Try to convert an object to a BigInt. Throws on failure (e.g. for Numbers).
    2332             :   // https://tc39.github.io/proposal-bigint/#sec-to-bigint
    2333             :   TNode<BigInt> ToBigInt(SloppyTNode<Context> context,
    2334             :                          SloppyTNode<Object> input);
    2335             : 
    2336             :   // Converts |input| to one of 2^32 integer values in the range 0 through
    2337             :   // 2^32-1, inclusive.
    2338             :   // ES#sec-touint32
    2339             :   TNode<Number> ToUint32(SloppyTNode<Context> context,
    2340             :                          SloppyTNode<Object> input);
    2341             : 
    2342             :   // Convert any object to a String.
    2343             :   TNode<String> ToString(SloppyTNode<Context> context,
    2344             :                          SloppyTNode<Object> input);
    2345             :   TNode<String> ToString_Inline(SloppyTNode<Context> context,
    2346             :                                 SloppyTNode<Object> input);
    2347             : 
    2348             :   // Convert any object to a Primitive.
    2349             :   Node* JSReceiverToPrimitive(Node* context, Node* input);
    2350             : 
    2351             :   TNode<JSReceiver> ToObject(SloppyTNode<Context> context,
    2352             :                              SloppyTNode<Object> input);
    2353             : 
    2354             :   // Same as ToObject but avoids the Builtin call if |input| is already a
    2355             :   // JSReceiver.
    2356             :   TNode<JSReceiver> ToObject_Inline(TNode<Context> context,
    2357             :                                     TNode<Object> input);
    2358             : 
    2359             :   enum ToIntegerTruncationMode {
    2360             :     kNoTruncation,
    2361             :     kTruncateMinusZero,
    2362             :   };
    2363             : 
    2364             :   // ES6 7.1.17 ToIndex, but jumps to range_error if the result is not a Smi.
    2365             :   TNode<Smi> ToSmiIndex(TNode<Context> context, TNode<Object> input,
    2366             :                         Label* range_error);
    2367             : 
    2368             :   // ES6 7.1.15 ToLength, but jumps to range_error if the result is not a Smi.
    2369             :   TNode<Smi> ToSmiLength(TNode<Context> context, TNode<Object> input,
    2370             :                          Label* range_error);
    2371             : 
    2372             :   // ES6 7.1.15 ToLength, but with inlined fast path.
    2373             :   TNode<Number> ToLength_Inline(SloppyTNode<Context> context,
    2374             :                                 SloppyTNode<Object> input);
    2375             : 
    2376             :   // ES6 7.1.4 ToInteger ( argument )
    2377             :   TNode<Number> ToInteger_Inline(SloppyTNode<Context> context,
    2378             :                                  SloppyTNode<Object> input,
    2379             :                                  ToIntegerTruncationMode mode = kNoTruncation);
    2380             :   TNode<Number> ToInteger(SloppyTNode<Context> context,
    2381             :                           SloppyTNode<Object> input,
    2382             :                           ToIntegerTruncationMode mode = kNoTruncation);
    2383             : 
    2384             :   // Returns a node that contains a decoded (unsigned!) value of a bit
    2385             :   // field |BitField| in |word32|. Returns result as an uint32 node.
    2386             :   template <typename BitField>
    2387       35212 :   TNode<Uint32T> DecodeWord32(SloppyTNode<Word32T> word32) {
    2388       35212 :     return DecodeWord32(word32, BitField::kShift, BitField::kMask);
    2389             :   }
    2390             : 
    2391             :   // Returns a node that contains a decoded (unsigned!) value of a bit
    2392             :   // field |BitField| in |word|. Returns result as a word-size node.
    2393             :   template <typename BitField>
    2394       21236 :   TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word) {
    2395       21240 :     return DecodeWord(word, BitField::kShift, BitField::kMask);
    2396             :   }
    2397             : 
    2398             :   // Returns a node that contains a decoded (unsigned!) value of a bit
    2399             :   // field |BitField| in |word32|. Returns result as a word-size node.
    2400             :   template <typename BitField>
    2401        6624 :   TNode<UintPtrT> DecodeWordFromWord32(SloppyTNode<Word32T> word32) {
    2402        6628 :     return DecodeWord<BitField>(ChangeUint32ToWord(word32));
    2403             :   }
    2404             : 
    2405             :   // Returns a node that contains a decoded (unsigned!) value of a bit
    2406             :   // field |BitField| in |word|. Returns result as an uint32 node.
    2407             :   template <typename BitField>
    2408         112 :   TNode<Uint32T> DecodeWord32FromWord(SloppyTNode<WordT> word) {
    2409             :     return UncheckedCast<Uint32T>(
    2410         112 :         TruncateIntPtrToInt32(Signed(DecodeWord<BitField>(word))));
    2411             :   }
    2412             : 
    2413             :   // Decodes an unsigned (!) value from |word32| to an uint32 node.
    2414             :   TNode<Uint32T> DecodeWord32(SloppyTNode<Word32T> word32, uint32_t shift,
    2415             :                               uint32_t mask);
    2416             : 
    2417             :   // Decodes an unsigned (!) value from |word| to a word-size node.
    2418             :   TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift,
    2419             :                              uint32_t mask);
    2420             : 
    2421             :   // Returns a node that contains the updated values of a |BitField|.
    2422             :   template <typename BitField>
    2423         392 :   TNode<WordT> UpdateWord(TNode<WordT> word, TNode<WordT> value) {
    2424         392 :     return UpdateWord(word, value, BitField::kShift, BitField::kMask);
    2425             :   }
    2426             : 
    2427             :   // Returns a node that contains the updated {value} inside {word} starting
    2428             :   // at {shift} and fitting in {mask}.
    2429             :   TNode<WordT> UpdateWord(TNode<WordT> word, TNode<WordT> value, uint32_t shift,
    2430             :                           uint32_t mask);
    2431             : 
    2432             :   // Returns true if any of the |T|'s bits in given |word32| are set.
    2433             :   template <typename T>
    2434       41632 :   TNode<BoolT> IsSetWord32(SloppyTNode<Word32T> word32) {
    2435       41632 :     return IsSetWord32(word32, T::kMask);
    2436             :   }
    2437             : 
    2438             :   // Returns true if any of the mask's bits in given |word32| are set.
    2439       56432 :   TNode<BoolT> IsSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) {
    2440      112864 :     return Word32NotEqual(Word32And(word32, Int32Constant(mask)),
    2441      169296 :                           Int32Constant(0));
    2442             :   }
    2443             : 
    2444             :   // Returns true if none of the mask's bits in given |word32| are set.
    2445         392 :   TNode<BoolT> IsNotSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) {
    2446         784 :     return Word32Equal(Word32And(word32, Int32Constant(mask)),
    2447        1176 :                        Int32Constant(0));
    2448             :   }
    2449             : 
    2450             :   // Returns true if all of the mask's bits in a given |word32| are set.
    2451        3980 :   TNode<BoolT> IsAllSetWord32(SloppyTNode<Word32T> word32, uint32_t mask) {
    2452        3980 :     TNode<Int32T> const_mask = Int32Constant(mask);
    2453        3980 :     return Word32Equal(Word32And(word32, const_mask), const_mask);
    2454             :   }
    2455             : 
    2456             :   // Returns true if any of the |T|'s bits in given |word| are set.
    2457             :   template <typename T>
    2458        7112 :   TNode<BoolT> IsSetWord(SloppyTNode<WordT> word) {
    2459        7112 :     return IsSetWord(word, T::kMask);
    2460             :   }
    2461             : 
    2462             :   // Returns true if any of the mask's bits in given |word| are set.
    2463       11260 :   TNode<BoolT> IsSetWord(SloppyTNode<WordT> word, uint32_t mask) {
    2464       11260 :     return WordNotEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
    2465             :   }
    2466             : 
    2467             :   // Returns true if any of the mask's bit are set in the given Smi.
    2468             :   // Smi-encoding of the mask is performed implicitly!
    2469         280 :   TNode<BoolT> IsSetSmi(SloppyTNode<Smi> smi, int untagged_mask) {
    2470         560 :     intptr_t mask_word = bit_cast<intptr_t>(Smi::FromInt(untagged_mask));
    2471             :     return WordNotEqual(
    2472         560 :         WordAnd(BitcastTaggedToWord(smi), IntPtrConstant(mask_word)),
    2473         840 :         IntPtrConstant(0));
    2474             :   }
    2475             : 
    2476             :   // Returns true if all of the |T|'s bits in given |word32| are clear.
    2477             :   template <typename T>
    2478         504 :   TNode<BoolT> IsClearWord32(SloppyTNode<Word32T> word32) {
    2479         504 :     return IsClearWord32(word32, T::kMask);
    2480             :   }
    2481             : 
    2482             :   // Returns true if all of the mask's bits in given |word32| are clear.
    2483        3536 :   TNode<BoolT> IsClearWord32(SloppyTNode<Word32T> word32, uint32_t mask) {
    2484        7072 :     return Word32Equal(Word32And(word32, Int32Constant(mask)),
    2485       10608 :                        Int32Constant(0));
    2486             :   }
    2487             : 
    2488             :   // Returns true if all of the |T|'s bits in given |word| are clear.
    2489             :   template <typename T>
    2490             :   TNode<BoolT> IsClearWord(SloppyTNode<WordT> word) {
    2491             :     return IsClearWord(word, T::kMask);
    2492             :   }
    2493             : 
    2494             :   // Returns true if all of the mask's bits in given |word| are clear.
    2495         728 :   TNode<BoolT> IsClearWord(SloppyTNode<WordT> word, uint32_t mask) {
    2496         728 :     return WordEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
    2497             :   }
    2498             : 
    2499             :   void SetCounter(StatsCounter* counter, int value);
    2500             :   void IncrementCounter(StatsCounter* counter, int delta);
    2501             :   void DecrementCounter(StatsCounter* counter, int delta);
    2502             : 
    2503             :   void Increment(Variable* variable, int value = 1,
    2504             :                  ParameterMode mode = INTPTR_PARAMETERS);
    2505          56 :   void Decrement(Variable* variable, int value = 1,
    2506             :                  ParameterMode mode = INTPTR_PARAMETERS) {
    2507          56 :     Increment(variable, -value, mode);
    2508          56 :   }
    2509             : 
    2510             :   // Generates "if (false) goto label" code. Useful for marking a label as
    2511             :   // "live" to avoid assertion failures during graph building. In the resulting
    2512             :   // code this check will be eliminated.
    2513             :   void Use(Label* label);
    2514             : 
    2515             :   // Various building blocks for stubs doing property lookups.
    2516             : 
    2517             :   // |if_notinternalized| is optional; |if_bailout| will be used by default.
    2518             :   // Note: If |key| does not yet have a hash, |if_notinternalized| will be taken
    2519             :   // even if |key| is an array index. |if_keyisunique| will never
    2520             :   // be taken for array indices.
    2521             :   void TryToName(Node* key, Label* if_keyisindex, Variable* var_index,
    2522             :                  Label* if_keyisunique, Variable* var_unique, Label* if_bailout,
    2523             :                  Label* if_notinternalized = nullptr);
    2524             : 
    2525             :   // Performs a hash computation and string table lookup for the given string,
    2526             :   // and jumps to:
    2527             :   // - |if_index| if the string is an array index like "123"; |var_index|
    2528             :   //              will contain the intptr representation of that index.
    2529             :   // - |if_internalized| if the string exists in the string table; the
    2530             :   //                     internalized version will be in |var_internalized|.
    2531             :   // - |if_not_internalized| if the string is not in the string table (but
    2532             :   //                         does not add it).
    2533             :   // - |if_bailout| for unsupported cases (e.g. uncachable array index).
    2534             :   void TryInternalizeString(Node* string, Label* if_index, Variable* var_index,
    2535             :                             Label* if_internalized, Variable* var_internalized,
    2536             :                             Label* if_not_internalized, Label* if_bailout);
    2537             : 
    2538             :   // Calculates array index for given dictionary entry and entry field.
    2539             :   // See Dictionary::EntryToIndex().
    2540             :   template <typename Dictionary>
    2541             :   TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry, int field_index);
    2542             :   template <typename Dictionary>
    2543       32276 :   TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry) {
    2544       32284 :     return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
    2545             :   }
    2546             : 
    2547             :   // Loads the details for the entry with the given key_index.
    2548             :   // Returns an untagged int32.
    2549             :   template <class ContainerType>
    2550        3756 :   TNode<Uint32T> LoadDetailsByKeyIndex(Node* container, Node* key_index) {
    2551             :     static_assert(!std::is_same<ContainerType, DescriptorArray>::value,
    2552             :                   "Use the non-templatized version for DescriptorArray");
    2553             :     const int kKeyToDetailsOffset =
    2554             :         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
    2555        3756 :         kTaggedSize;
    2556        7512 :     return Unsigned(LoadAndUntagToWord32FixedArrayElement(
    2557       11268 :         CAST(container), key_index, kKeyToDetailsOffset));
    2558             :   }
    2559             : 
    2560             :   // Loads the value for the entry with the given key_index.
    2561             :   // Returns a tagged value.
    2562             :   template <class ContainerType>
    2563        3532 :   TNode<Object> LoadValueByKeyIndex(Node* container, Node* key_index) {
    2564             :     static_assert(!std::is_same<ContainerType, DescriptorArray>::value,
    2565             :                   "Use the non-templatized version for DescriptorArray");
    2566             :     const int kKeyToValueOffset =
    2567             :         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
    2568        3532 :         kTaggedSize;
    2569        3532 :     return LoadFixedArrayElement(CAST(container), key_index, kKeyToValueOffset);
    2570             :   }
    2571             : 
    2572             :   // Stores the details for the entry with the given key_index.
    2573             :   // |details| must be a Smi.
    2574             :   template <class ContainerType>
    2575        1064 :   void StoreDetailsByKeyIndex(TNode<ContainerType> container,
    2576             :                               TNode<IntPtrT> key_index, TNode<Smi> details) {
    2577             :     const int kKeyToDetailsOffset =
    2578             :         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
    2579        1064 :         kTaggedSize;
    2580        1064 :     StoreFixedArrayElement(container, key_index, details, SKIP_WRITE_BARRIER,
    2581             :                            kKeyToDetailsOffset);
    2582        1064 :   }
    2583             : 
    2584             :   // Stores the value for the entry with the given key_index.
    2585             :   template <class ContainerType>
    2586        1680 :   void StoreValueByKeyIndex(
    2587             :       TNode<ContainerType> container, TNode<IntPtrT> key_index,
    2588             :       TNode<Object> value,
    2589             :       WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER) {
    2590             :     const int kKeyToValueOffset =
    2591             :         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
    2592        1680 :         kTaggedSize;
    2593        1680 :     StoreFixedArrayElement(container, key_index, value, write_barrier,
    2594             :                            kKeyToValueOffset);
    2595        1680 :   }
    2596             : 
    2597             :   // Calculate a valid size for the a hash table.
    2598             :   TNode<IntPtrT> HashTableComputeCapacity(TNode<IntPtrT> at_least_space_for);
    2599             : 
    2600             :   template <class Dictionary>
    2601        1400 :   TNode<Smi> GetNumberOfElements(TNode<Dictionary> dictionary) {
    2602        1400 :     return CAST(
    2603             :         LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex));
    2604             :   }
    2605             : 
    2606         112 :   TNode<Smi> GetNumberDictionaryNumberOfElements(
    2607             :       TNode<NumberDictionary> dictionary) {
    2608         112 :     return GetNumberOfElements<NumberDictionary>(dictionary);
    2609             :   }
    2610             : 
    2611             :   template <class Dictionary>
    2612        1064 :   void SetNumberOfElements(TNode<Dictionary> dictionary,
    2613             :                            TNode<Smi> num_elements_smi) {
    2614        1064 :     StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex,
    2615             :                            num_elements_smi, SKIP_WRITE_BARRIER);
    2616        1064 :   }
    2617             : 
    2618             :   template <class Dictionary>
    2619        1064 :   TNode<Smi> GetNumberOfDeletedElements(TNode<Dictionary> dictionary) {
    2620        1064 :     return CAST(LoadFixedArrayElement(
    2621             :         dictionary, Dictionary::kNumberOfDeletedElementsIndex));
    2622             :   }
    2623             : 
    2624             :   template <class Dictionary>
    2625          56 :   void SetNumberOfDeletedElements(TNode<Dictionary> dictionary,
    2626             :                                   TNode<Smi> num_deleted_smi) {
    2627          56 :     StoreFixedArrayElement(dictionary,
    2628             :                            Dictionary::kNumberOfDeletedElementsIndex,
    2629             :                            num_deleted_smi, SKIP_WRITE_BARRIER);
    2630          56 :   }
    2631             : 
    2632             :   template <class Dictionary>
    2633        9160 :   TNode<Smi> GetCapacity(TNode<Dictionary> dictionary) {
    2634        9160 :     return CAST(
    2635             :         UnsafeLoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex));
    2636             :   }
    2637             : 
    2638             :   template <class Dictionary>
    2639        1008 :   TNode<Smi> GetNextEnumerationIndex(TNode<Dictionary> dictionary) {
    2640        1008 :     return CAST(LoadFixedArrayElement(dictionary,
    2641             :                                       Dictionary::kNextEnumerationIndexIndex));
    2642             :   }
    2643             : 
    2644             :   template <class Dictionary>
    2645        1008 :   void SetNextEnumerationIndex(TNode<Dictionary> dictionary,
    2646             :                                TNode<Smi> next_enum_index_smi) {
    2647        1008 :     StoreFixedArrayElement(dictionary, Dictionary::kNextEnumerationIndexIndex,
    2648             :                            next_enum_index_smi, SKIP_WRITE_BARRIER);
    2649        1008 :   }
    2650             : 
    2651             :   // Looks up an entry in a NameDictionaryBase successor. If the entry is found
    2652             :   // control goes to {if_found} and {var_name_index} contains an index of the
    2653             :   // key field of the entry found. If the key is not found control goes to
    2654             :   // {if_not_found}.
    2655             :   static const int kInlinedDictionaryProbes = 4;
    2656             :   enum LookupMode { kFindExisting, kFindInsertionIndex };
    2657             : 
    2658             :   template <typename Dictionary>
    2659             :   TNode<HeapObject> LoadName(TNode<HeapObject> key);
    2660             : 
    2661             :   template <typename Dictionary>
    2662             :   void NameDictionaryLookup(TNode<Dictionary> dictionary,
    2663             :                             TNode<Name> unique_name, Label* if_found,
    2664             :                             TVariable<IntPtrT>* var_name_index,
    2665             :                             Label* if_not_found,
    2666             :                             int inlined_probes = kInlinedDictionaryProbes,
    2667             :                             LookupMode mode = kFindExisting);
    2668             : 
    2669             :   Node* ComputeUnseededHash(Node* key);
    2670             :   Node* ComputeSeededHash(Node* key);
    2671             : 
    2672             :   void NumberDictionaryLookup(TNode<NumberDictionary> dictionary,
    2673             :                               TNode<IntPtrT> intptr_index, Label* if_found,
    2674             :                               TVariable<IntPtrT>* var_entry,
    2675             :                               Label* if_not_found);
    2676             : 
    2677             :   TNode<Object> BasicLoadNumberDictionaryElement(
    2678             :       TNode<NumberDictionary> dictionary, TNode<IntPtrT> intptr_index,
    2679             :       Label* not_data, Label* if_hole);
    2680             :   void BasicStoreNumberDictionaryElement(TNode<NumberDictionary> dictionary,
    2681             :                                          TNode<IntPtrT> intptr_index,
    2682             :                                          TNode<Object> value, Label* not_data,
    2683             :                                          Label* if_hole, Label* read_only);
    2684             : 
    2685             :   template <class Dictionary>
    2686             :   void FindInsertionEntry(TNode<Dictionary> dictionary, TNode<Name> key,
    2687             :                           TVariable<IntPtrT>* var_key_index);
    2688             : 
    2689             :   template <class Dictionary>
    2690             :   void InsertEntry(TNode<Dictionary> dictionary, TNode<Name> key,
    2691             :                    TNode<Object> value, TNode<IntPtrT> index,
    2692             :                    TNode<Smi> enum_index);
    2693             : 
    2694             :   template <class Dictionary>
    2695             :   void Add(TNode<Dictionary> dictionary, TNode<Name> key, TNode<Object> value,
    2696             :            Label* bailout);
    2697             : 
    2698             :   // Tries to check if {object} has own {unique_name} property.
    2699             :   void TryHasOwnProperty(Node* object, Node* map, Node* instance_type,
    2700             :                          Node* unique_name, Label* if_found,
    2701             :                          Label* if_not_found, Label* if_bailout);
    2702             : 
    2703             :   // Operating mode for TryGetOwnProperty and CallGetterIfAccessor
    2704             :   // kReturnAccessorPair is used when we're only getting the property descriptor
    2705             :   enum GetOwnPropertyMode { kCallJSGetter, kReturnAccessorPair };
    2706             :   // Tries to get {object}'s own {unique_name} property value. If the property
    2707             :   // is an accessor then it also calls a getter. If the property is a double
    2708             :   // field it re-wraps value in an immutable heap number. {unique_name} must be
    2709             :   // a unique name (Symbol or InternalizedString) that is not an array index.
    2710             :   void TryGetOwnProperty(Node* context, Node* receiver, Node* object, Node* map,
    2711             :                          Node* instance_type, Node* unique_name,
    2712             :                          Label* if_found, Variable* var_value,
    2713             :                          Label* if_not_found, Label* if_bailout);
    2714             :   void TryGetOwnProperty(Node* context, Node* receiver, Node* object, Node* map,
    2715             :                          Node* instance_type, Node* unique_name,
    2716             :                          Label* if_found, Variable* var_value,
    2717             :                          Variable* var_details, Variable* var_raw_value,
    2718             :                          Label* if_not_found, Label* if_bailout,
    2719             :                          GetOwnPropertyMode mode);
    2720             : 
    2721        8344 :   TNode<Object> GetProperty(SloppyTNode<Context> context,
    2722             :                             SloppyTNode<Object> receiver, Handle<Name> name) {
    2723        8344 :     return GetProperty(context, receiver, HeapConstant(name));
    2724             :   }
    2725             : 
    2726       12264 :   TNode<Object> GetProperty(SloppyTNode<Context> context,
    2727             :                             SloppyTNode<Object> receiver,
    2728             :                             SloppyTNode<Object> name) {
    2729       12264 :     return CallBuiltin(Builtins::kGetProperty, context, receiver, name);
    2730             :   }
    2731             : 
    2732        1680 :   TNode<Object> SetPropertyStrict(TNode<Context> context,
    2733             :                                   TNode<Object> receiver, TNode<Object> key,
    2734             :                                   TNode<Object> value) {
    2735        1680 :     return CallBuiltin(Builtins::kSetProperty, context, receiver, key, value);
    2736             :   }
    2737             : 
    2738          56 :   TNode<Object> SetPropertyInLiteral(TNode<Context> context,
    2739             :                                      TNode<JSObject> receiver,
    2740             :                                      TNode<Object> key, TNode<Object> value) {
    2741             :     return CallBuiltin(Builtins::kSetPropertyInLiteral, context, receiver, key,
    2742          56 :                        value);
    2743             :   }
    2744             : 
    2745             :   Node* GetMethod(Node* context, Node* object, Handle<Name> name,
    2746             :                   Label* if_null_or_undefined);
    2747             : 
    2748             :   TNode<Object> GetIteratorMethod(TNode<Context> context,
    2749             :                                   TNode<HeapObject> heap_obj,
    2750             :                                   Label* if_iteratorundefined);
    2751             : 
    2752             :   template <class... TArgs>
    2753       78300 :   TNode<Object> CallBuiltin(Builtins::Name id, SloppyTNode<Object> context,
    2754             :                             TArgs... args) {
    2755             :     return CallStub<Object>(Builtins::CallableFor(isolate(), id), context,
    2756       78308 :                             args...);
    2757             :   }
    2758             : 
    2759             :   template <class... TArgs>
    2760        3024 :   void TailCallBuiltin(Builtins::Name id, SloppyTNode<Object> context,
    2761             :                        TArgs... args) {
    2762        3024 :     return TailCallStub(Builtins::CallableFor(isolate(), id), context, args...);
    2763             :   }
    2764             : 
    2765             :   void LoadPropertyFromFastObject(Node* object, Node* map,
    2766             :                                   TNode<DescriptorArray> descriptors,
    2767             :                                   Node* name_index, Variable* var_details,
    2768             :                                   Variable* var_value);
    2769             : 
    2770             :   void LoadPropertyFromFastObject(Node* object, Node* map,
    2771             :                                   TNode<DescriptorArray> descriptors,
    2772             :                                   Node* name_index, Node* details,
    2773             :                                   Variable* var_value);
    2774             : 
    2775             :   void LoadPropertyFromNameDictionary(Node* dictionary, Node* entry,
    2776             :                                       Variable* var_details,
    2777             :                                       Variable* var_value);
    2778             : 
    2779             :   void LoadPropertyFromGlobalDictionary(Node* dictionary, Node* entry,
    2780             :                                         Variable* var_details,
    2781             :                                         Variable* var_value, Label* if_deleted);
    2782             : 
    2783             :   // Generic property lookup generator. If the {object} is fast and
    2784             :   // {unique_name} property is found then the control goes to {if_found_fast}
    2785             :   // label and {var_meta_storage} and {var_name_index} will contain
    2786             :   // DescriptorArray and an index of the descriptor's name respectively.
    2787             :   // If the {object} is slow or global then the control goes to {if_found_dict}
    2788             :   // or {if_found_global} and the {var_meta_storage} and {var_name_index} will
    2789             :   // contain a dictionary and an index of the key field of the found entry.
    2790             :   // If property is not found or given lookup is not supported then
    2791             :   // the control goes to {if_not_found} or {if_bailout} respectively.
    2792             :   //
    2793             :   // Note: this code does not check if the global dictionary points to deleted
    2794             :   // entry! This has to be done by the caller.
    2795             :   void TryLookupProperty(SloppyTNode<JSObject> object, SloppyTNode<Map> map,
    2796             :                          SloppyTNode<Int32T> instance_type,
    2797             :                          SloppyTNode<Name> unique_name, Label* if_found_fast,
    2798             :                          Label* if_found_dict, Label* if_found_global,
    2799             :                          TVariable<HeapObject>* var_meta_storage,
    2800             :                          TVariable<IntPtrT>* var_name_index,
    2801             :                          Label* if_not_found, Label* if_bailout);
    2802             : 
    2803             :   // This is a building block for TryLookupProperty() above. Supports only
    2804             :   // non-special fast and dictionary objects.
    2805             :   void TryLookupPropertyInSimpleObject(TNode<JSObject> object, TNode<Map> map,
    2806             :                                        TNode<Name> unique_name,
    2807             :                                        Label* if_found_fast,
    2808             :                                        Label* if_found_dict,
    2809             :                                        TVariable<HeapObject>* var_meta_storage,
    2810             :                                        TVariable<IntPtrT>* var_name_index,
    2811             :                                        Label* if_not_found);
    2812             : 
    2813             :   // This method jumps to if_found if the element is known to exist. To
    2814             :   // if_absent if it's known to not exist. To if_not_found if the prototype
    2815             :   // chain needs to be checked. And if_bailout if the lookup is unsupported.
    2816             :   void TryLookupElement(Node* object, Node* map,
    2817             :                         SloppyTNode<Int32T> instance_type,
    2818             :                         SloppyTNode<IntPtrT> intptr_index, Label* if_found,
    2819             :                         Label* if_absent, Label* if_not_found,
    2820             :                         Label* if_bailout);
    2821             : 
    2822             :   // This is a type of a lookup in holder generator function. In case of a
    2823             :   // property lookup the {key} is guaranteed to be an unique name and in case of
    2824             :   // element lookup the key is an Int32 index.
    2825             :   typedef std::function<void(Node* receiver, Node* holder, Node* map,
    2826             :                              Node* instance_type, Node* key, Label* next_holder,
    2827             :                              Label* if_bailout)>
    2828             :       LookupInHolder;
    2829             : 
    2830             :   // For integer indexed exotic cases, check if the given string cannot be a
    2831             :   // special index. If we are not sure that the given string is not a special
    2832             :   // index with a simple check, return False. Note that "False" return value
    2833             :   // does not mean that the name_string is a special index in the current
    2834             :   // implementation.
    2835             :   void BranchIfMaybeSpecialIndex(TNode<String> name_string,
    2836             :                                  Label* if_maybe_special_index,
    2837             :                                  Label* if_not_special_index);
    2838             : 
    2839             :   // Generic property prototype chain lookup generator.
    2840             :   // For properties it generates lookup using given {lookup_property_in_holder}
    2841             :   // and for elements it uses {lookup_element_in_holder}.
    2842             :   // Upon reaching the end of prototype chain the control goes to {if_end}.
    2843             :   // If it can't handle the case {receiver}/{key} case then the control goes
    2844             :   // to {if_bailout}.
    2845             :   // If {if_proxy} is nullptr, proxies go to if_bailout.
    2846             :   void TryPrototypeChainLookup(Node* receiver, Node* key,
    2847             :                                const LookupInHolder& lookup_property_in_holder,
    2848             :                                const LookupInHolder& lookup_element_in_holder,
    2849             :                                Label* if_end, Label* if_bailout,
    2850             :                                Label* if_proxy = nullptr);
    2851             : 
    2852             :   // Instanceof helpers.
    2853             :   // Returns true if {object} has {prototype} somewhere in it's prototype
    2854             :   // chain, otherwise false is returned. Might cause arbitrary side effects
    2855             :   // due to [[GetPrototypeOf]] invocations.
    2856             :   Node* HasInPrototypeChain(Node* context, Node* object, Node* prototype);
    2857             :   // ES6 section 7.3.19 OrdinaryHasInstance (C, O)
    2858             :   Node* OrdinaryHasInstance(Node* context, Node* callable, Node* object);
    2859             : 
    2860             :   // Load type feedback vector from the stub caller's frame.
    2861             :   TNode<FeedbackVector> LoadFeedbackVectorForStub();
    2862             : 
    2863             :   // Load the value from closure's feedback cell.
    2864             :   TNode<HeapObject> LoadFeedbackCellValue(SloppyTNode<JSFunction> closure);
    2865             : 
    2866             :   // Load the object from feedback vector cell for the given closure.
    2867             :   // The returned object could be undefined if the closure does not have
    2868             :   // a feedback vector associated with it.
    2869             :   TNode<HeapObject> LoadFeedbackVector(SloppyTNode<JSFunction> closure);
    2870             : 
    2871             :   // Load the ClosureFeedbackCellArray that contains the feedback cells
    2872             :   // used when creating closures from this function. This array could be
    2873             :   // directly hanging off the FeedbackCell when there is no feedback vector
    2874             :   // or available from the feedback vector's header.
    2875             :   TNode<FixedArray> LoadClosureFeedbackArray(SloppyTNode<JSFunction> closure);
    2876             : 
    2877             :   // Update the type feedback vector.
    2878             :   void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id);
    2879             : 
    2880             : 
    2881             :   // Report that there was a feedback update, performing any tasks that should
    2882             :   // be done after a feedback update.
    2883             :   void ReportFeedbackUpdate(SloppyTNode<FeedbackVector> feedback_vector,
    2884             :                             SloppyTNode<IntPtrT> slot_id, const char* reason);
    2885             : 
    2886             :   // Combine the new feedback with the existing_feedback. Do nothing if
    2887             :   // existing_feedback is nullptr.
    2888             :   void CombineFeedback(Variable* existing_feedback, int feedback);
    2889             :   void CombineFeedback(Variable* existing_feedback, Node* feedback);
    2890             : 
    2891             :   // Overwrite the existing feedback with new_feedback. Do nothing if
    2892             :   // existing_feedback is nullptr.
    2893             :   void OverwriteFeedback(Variable* existing_feedback, int new_feedback);
    2894             : 
    2895             :   // Check if a property name might require protector invalidation when it is
    2896             :   // used for a property store or deletion.
    2897             :   void CheckForAssociatedProtector(Node* name, Label* if_protector);
    2898             : 
    2899             :   TNode<Map> LoadReceiverMap(SloppyTNode<Object> receiver);
    2900             : 
    2901             :   enum class ArgumentsAccessMode { kLoad, kStore, kHas };
    2902             :   // Emits keyed sloppy arguments has. Returns whether the key is in the
    2903             :   // arguments.
    2904          56 :   Node* HasKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
    2905             :     return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
    2906          56 :                                     ArgumentsAccessMode::kHas);
    2907             :   }
    2908             : 
    2909             :   // Emits keyed sloppy arguments load. Returns either the loaded value.
    2910          56 :   Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
    2911             :     return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout,
    2912          56 :                                     ArgumentsAccessMode::kLoad);
    2913             :   }
    2914             : 
    2915             :   // Emits keyed sloppy arguments store.
    2916         224 :   void StoreKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
    2917             :                                  Label* bailout) {
    2918             :     DCHECK_NOT_NULL(value);
    2919             :     EmitKeyedSloppyArguments(receiver, key, value, bailout,
    2920         224 :                              ArgumentsAccessMode::kStore);
    2921         224 :   }
    2922             : 
    2923             :   // Loads script context from the script context table.
    2924             :   TNode<Context> LoadScriptContext(TNode<Context> context,
    2925             :                                    TNode<IntPtrT> context_index);
    2926             : 
    2927             :   Node* Int32ToUint8Clamped(Node* int32_value);
    2928             :   Node* Float64ToUint8Clamped(Node* float64_value);
    2929             : 
    2930             :   Node* PrepareValueForWriteToTypedArray(TNode<Object> input,
    2931             :                                          ElementsKind elements_kind,
    2932             :                                          TNode<Context> context);
    2933             : 
    2934             :   // Store value to an elements array with given elements kind.
    2935             :   void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
    2936             :                     ParameterMode mode);
    2937             : 
    2938             :   void EmitBigTypedArrayElementStore(TNode<JSTypedArray> object,
    2939             :                                      TNode<FixedTypedArrayBase> elements,
    2940             :                                      TNode<IntPtrT> intptr_key,
    2941             :                                      TNode<Object> value,
    2942             :                                      TNode<Context> context,
    2943             :                                      Label* opt_if_detached);
    2944             :   // Part of the above, refactored out to reuse in another place.
    2945             :   void EmitBigTypedArrayElementStore(TNode<FixedTypedArrayBase> elements,
    2946             :                                      TNode<RawPtrT> backing_store,
    2947             :                                      TNode<IntPtrT> offset,
    2948             :                                      TNode<BigInt> bigint_value);
    2949             :   // Implements the BigInt part of
    2950             :   // https://tc39.github.io/proposal-bigint/#sec-numbertorawbytes,
    2951             :   // including truncation to 64 bits (i.e. modulo 2^64).
    2952             :   // {var_high} is only used on 32-bit platforms.
    2953             :   void BigIntToRawBytes(TNode<BigInt> bigint, TVariable<UintPtrT>* var_low,
    2954             :                         TVariable<UintPtrT>* var_high);
    2955             : 
    2956             :   void EmitElementStore(Node* object, Node* key, Node* value,
    2957             :                         ElementsKind elements_kind,
    2958             :                         KeyedAccessStoreMode store_mode, Label* bailout,
    2959             :                         Node* context);
    2960             : 
    2961             :   Node* CheckForCapacityGrow(Node* object, Node* elements, ElementsKind kind,
    2962             :                              Node* length, Node* key, ParameterMode mode,
    2963             :                              Label* bailout);
    2964             : 
    2965             :   Node* CopyElementsOnWrite(Node* object, Node* elements, ElementsKind kind,
    2966             :                             Node* length, ParameterMode mode, Label* bailout);
    2967             : 
    2968             :   void TransitionElementsKind(Node* object, Node* map, ElementsKind from_kind,
    2969             :                               ElementsKind to_kind, Label* bailout);
    2970             : 
    2971             :   void TrapAllocationMemento(Node* object, Label* memento_found);
    2972             : 
    2973             :   TNode<IntPtrT> PageFromAddress(TNode<IntPtrT> address);
    2974             : 
    2975             :   // Store a weak in-place reference into the FeedbackVector.
    2976             :   TNode<MaybeObject> StoreWeakReferenceInFeedbackVector(
    2977             :       SloppyTNode<FeedbackVector> feedback_vector, Node* slot,
    2978             :       SloppyTNode<HeapObject> value, int additional_offset = 0,
    2979             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
    2980             : 
    2981             :   // Create a new AllocationSite and install it into a feedback vector.
    2982             :   TNode<AllocationSite> CreateAllocationSiteInFeedbackVector(
    2983             :       SloppyTNode<FeedbackVector> feedback_vector, TNode<Smi> slot);
    2984             : 
    2985             :   // TODO(ishell, cbruni): Change to HasBoilerplate.
    2986             :   TNode<BoolT> NotHasBoilerplate(TNode<Object> maybe_literal_site);
    2987             :   TNode<Smi> LoadTransitionInfo(TNode<AllocationSite> allocation_site);
    2988             :   TNode<JSObject> LoadBoilerplate(TNode<AllocationSite> allocation_site);
    2989             :   TNode<Int32T> LoadElementsKind(TNode<AllocationSite> allocation_site);
    2990             : 
    2991             :   enum class IndexAdvanceMode { kPre, kPost };
    2992             : 
    2993             :   typedef std::function<void(Node* index)> FastLoopBody;
    2994             : 
    2995             :   Node* BuildFastLoop(const VariableList& var_list, Node* start_index,
    2996             :                       Node* end_index, const FastLoopBody& body, int increment,
    2997             :                       ParameterMode parameter_mode,
    2998             :                       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre);
    2999             : 
    3000        8660 :   Node* BuildFastLoop(Node* start_index, Node* end_index,
    3001             :                       const FastLoopBody& body, int increment,
    3002             :                       ParameterMode parameter_mode,
    3003             :                       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre) {
    3004       17320 :     return BuildFastLoop(VariableList(0, zone()), start_index, end_index, body,
    3005       17320 :                          increment, parameter_mode, advance_mode);
    3006             :   }
    3007             : 
    3008             :   enum class ForEachDirection { kForward, kReverse };
    3009             : 
    3010             :   typedef std::function<void(Node* fixed_array, Node* offset)>
    3011             :       FastFixedArrayForEachBody;
    3012             : 
    3013             :   void BuildFastFixedArrayForEach(
    3014             :       const CodeStubAssembler::VariableList& vars, Node* fixed_array,
    3015             :       ElementsKind kind, Node* first_element_inclusive,
    3016             :       Node* last_element_exclusive, const FastFixedArrayForEachBody& body,
    3017             :       ParameterMode mode = INTPTR_PARAMETERS,
    3018             :       ForEachDirection direction = ForEachDirection::kReverse);
    3019             : 
    3020       16772 :   void BuildFastFixedArrayForEach(
    3021             :       Node* fixed_array, ElementsKind kind, Node* first_element_inclusive,
    3022             :       Node* last_element_exclusive, const FastFixedArrayForEachBody& body,
    3023             :       ParameterMode mode = INTPTR_PARAMETERS,
    3024             :       ForEachDirection direction = ForEachDirection::kReverse) {
    3025       33544 :     CodeStubAssembler::VariableList list(0, zone());
    3026       16772 :     BuildFastFixedArrayForEach(list, fixed_array, kind, first_element_inclusive,
    3027       16772 :                                last_element_exclusive, body, mode, direction);
    3028       16772 :   }
    3029             : 
    3030       16076 :   TNode<IntPtrT> GetArrayAllocationSize(Node* element_count, ElementsKind kind,
    3031             :                                         ParameterMode mode, int header_size) {
    3032       16076 :     return ElementOffsetFromIndex(element_count, kind, mode, header_size);
    3033             :   }
    3034             : 
    3035       12044 :   TNode<IntPtrT> GetFixedArrayAllocationSize(Node* element_count,
    3036             :                                              ElementsKind kind,
    3037             :                                              ParameterMode mode) {
    3038             :     return GetArrayAllocationSize(element_count, kind, mode,
    3039       12044 :                                   FixedArray::kHeaderSize);
    3040             :   }
    3041             : 
    3042         504 :   TNode<IntPtrT> GetPropertyArrayAllocationSize(Node* element_count,
    3043             :                                                 ParameterMode mode) {
    3044             :     return GetArrayAllocationSize(element_count, PACKED_ELEMENTS, mode,
    3045         504 :                                   PropertyArray::kHeaderSize);
    3046             :   }
    3047             : 
    3048             :   void GotoIfFixedArraySizeDoesntFitInNewSpace(Node* element_count,
    3049             :                                                Label* doesnt_fit, int base_size,
    3050             :                                                ParameterMode mode);
    3051             : 
    3052             :   void InitializeFieldsWithRoot(Node* object, Node* start_offset,
    3053             :                                 Node* end_offset, RootIndex root);
    3054             : 
    3055             :   Node* RelationalComparison(Operation op, Node* left, Node* right,
    3056             :                              Node* context,
    3057             :                              Variable* var_type_feedback = nullptr);
    3058             : 
    3059             :   void BranchIfNumberRelationalComparison(Operation op, Node* left, Node* right,
    3060             :                                           Label* if_true, Label* if_false);
    3061             : 
    3062         336 :   void BranchIfNumberEqual(TNode<Number> left, TNode<Number> right,
    3063             :                            Label* if_true, Label* if_false) {
    3064         336 :     BranchIfNumberRelationalComparison(Operation::kEqual, left, right, if_true,
    3065         336 :                                        if_false);
    3066         336 :   }
    3067             : 
    3068             :   void BranchIfNumberNotEqual(TNode<Number> left, TNode<Number> right,
    3069             :                               Label* if_true, Label* if_false) {
    3070             :     BranchIfNumberEqual(left, right, if_false, if_true);
    3071             :   }
    3072             : 
    3073        3136 :   void BranchIfNumberLessThan(TNode<Number> left, TNode<Number> right,
    3074             :                               Label* if_true, Label* if_false) {
    3075        3136 :     BranchIfNumberRelationalComparison(Operation::kLessThan, left, right,
    3076        3136 :                                        if_true, if_false);
    3077        3136 :   }
    3078             : 
    3079          56 :   void BranchIfNumberLessThanOrEqual(TNode<Number> left, TNode<Number> right,
    3080             :                                      Label* if_true, Label* if_false) {
    3081          56 :     BranchIfNumberRelationalComparison(Operation::kLessThanOrEqual, left, right,
    3082          56 :                                        if_true, if_false);
    3083          56 :   }
    3084             : 
    3085        1904 :   void BranchIfNumberGreaterThan(TNode<Number> left, TNode<Number> right,
    3086             :                                  Label* if_true, Label* if_false) {
    3087        1904 :     BranchIfNumberRelationalComparison(Operation::kGreaterThan, left, right,
    3088        1904 :                                        if_true, if_false);
    3089        1904 :   }
    3090             : 
    3091         336 :   void BranchIfNumberGreaterThanOrEqual(TNode<Number> left, TNode<Number> right,
    3092             :                                         Label* if_true, Label* if_false) {
    3093         336 :     BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, left,
    3094         336 :                                        right, if_true, if_false);
    3095         336 :   }
    3096             : 
    3097         168 :   void BranchIfAccessorPair(Node* value, Label* if_accessor_pair,
    3098             :                             Label* if_not_accessor_pair) {
    3099         168 :     GotoIf(TaggedIsSmi(value), if_not_accessor_pair);
    3100         168 :     Branch(IsAccessorPair(value), if_accessor_pair, if_not_accessor_pair);
    3101         168 :   }
    3102             : 
    3103             :   void GotoIfNumberGreaterThanOrEqual(Node* left, Node* right, Label* if_false);
    3104             : 
    3105             :   Node* Equal(Node* lhs, Node* rhs, Node* context,
    3106             :               Variable* var_type_feedback = nullptr);
    3107             : 
    3108             :   Node* StrictEqual(Node* lhs, Node* rhs,
    3109             :                     Variable* var_type_feedback = nullptr);
    3110             : 
    3111             :   // ECMA#sec-samevalue
    3112             :   // Similar to StrictEqual except that NaNs are treated as equal and minus zero
    3113             :   // differs from positive zero.
    3114             :   void BranchIfSameValue(Node* lhs, Node* rhs, Label* if_true, Label* if_false);
    3115             : 
    3116             :   enum HasPropertyLookupMode { kHasProperty, kForInHasProperty };
    3117             : 
    3118             :   TNode<Oddball> HasProperty(SloppyTNode<Context> context,
    3119             :                              SloppyTNode<Object> object,
    3120             :                              SloppyTNode<Object> key,
    3121             :                              HasPropertyLookupMode mode);
    3122             : 
    3123             :   // Due to naming conflict with the builtin function namespace.
    3124         392 :   TNode<Oddball> HasProperty_Inline(TNode<Context> context,
    3125             :                                     TNode<JSReceiver> object,
    3126             :                                     TNode<Object> key) {
    3127             :     return HasProperty(context, object, key,
    3128         392 :                        HasPropertyLookupMode::kHasProperty);
    3129             :   }
    3130             : 
    3131             :   Node* Typeof(Node* value);
    3132             : 
    3133             :   TNode<Object> GetSuperConstructor(SloppyTNode<Context> context,
    3134             :                                     SloppyTNode<JSFunction> active_function);
    3135             : 
    3136             :   TNode<JSReceiver> SpeciesConstructor(
    3137             :       SloppyTNode<Context> context, SloppyTNode<Object> object,
    3138             :       SloppyTNode<JSReceiver> default_constructor);
    3139             : 
    3140             :   Node* InstanceOf(Node* object, Node* callable, Node* context);
    3141             : 
    3142             :   // Debug helpers
    3143             :   Node* IsDebugActive();
    3144             : 
    3145             :   TNode<BoolT> IsRuntimeCallStatsEnabled();
    3146             : 
    3147             :   // JSArrayBuffer helpers
    3148             :   TNode<Uint32T> LoadJSArrayBufferBitField(TNode<JSArrayBuffer> array_buffer);
    3149             :   TNode<RawPtrT> LoadJSArrayBufferBackingStore(
    3150             :       TNode<JSArrayBuffer> array_buffer);
    3151             :   Node* IsDetachedBuffer(Node* buffer);
    3152             :   void ThrowIfArrayBufferIsDetached(SloppyTNode<Context> context,
    3153             :                                     TNode<JSArrayBuffer> array_buffer,
    3154             :                                     const char* method_name);
    3155             : 
    3156             :   // JSArrayBufferView helpers
    3157             :   TNode<JSArrayBuffer> LoadJSArrayBufferViewBuffer(
    3158             :       TNode<JSArrayBufferView> array_buffer_view);
    3159             :   TNode<UintPtrT> LoadJSArrayBufferViewByteLength(
    3160             :       TNode<JSArrayBufferView> array_buffer_view);
    3161             :   TNode<UintPtrT> LoadJSArrayBufferViewByteOffset(
    3162             :       TNode<JSArrayBufferView> array_buffer_view);
    3163             :   void ThrowIfArrayBufferViewBufferIsDetached(
    3164             :       SloppyTNode<Context> context, TNode<JSArrayBufferView> array_buffer_view,
    3165             :       const char* method_name);
    3166             : 
    3167             :   // JSTypedArray helpers
    3168             :   TNode<Smi> LoadJSTypedArrayLength(TNode<JSTypedArray> typed_array);
    3169             : 
    3170             :   TNode<IntPtrT> ElementOffsetFromIndex(Node* index, ElementsKind kind,
    3171             :                                         ParameterMode mode, int base_size = 0);
    3172             : 
    3173             :   // Check that a field offset is within the bounds of the an object.
    3174             :   TNode<BoolT> IsOffsetInBounds(SloppyTNode<IntPtrT> offset,
    3175             :                                 SloppyTNode<IntPtrT> length, int header_size,
    3176             :                                 ElementsKind kind = HOLEY_ELEMENTS);
    3177             : 
    3178             :   // Load a builtin's code from the builtin array in the isolate.
    3179             :   TNode<Code> LoadBuiltin(TNode<Smi> builtin_id);
    3180             : 
    3181             :   // Figure out the SFI's code object using its data field.
    3182             :   // If |if_compile_lazy| is provided then the execution will go to the given
    3183             :   // label in case of an CompileLazy code object.
    3184             :   TNode<Code> GetSharedFunctionInfoCode(
    3185             :       SloppyTNode<SharedFunctionInfo> shared_info,
    3186             :       Label* if_compile_lazy = nullptr);
    3187             : 
    3188             :   Node* AllocateFunctionWithMapAndContext(Node* map, Node* shared_info,
    3189             :                                           Node* context);
    3190             : 
    3191             :   // Promise helpers
    3192             :   Node* IsPromiseHookEnabled();
    3193             :   Node* HasAsyncEventDelegate();
    3194             :   Node* IsPromiseHookEnabledOrHasAsyncEventDelegate();
    3195             :   Node* IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate();
    3196             : 
    3197             :   // Helpers for StackFrame markers.
    3198             :   Node* MarkerIsFrameType(Node* marker_or_function,
    3199             :                           StackFrame::Type frame_type);
    3200             :   Node* MarkerIsNotFrameType(Node* marker_or_function,
    3201             :                              StackFrame::Type frame_type);
    3202             : 
    3203             :   // for..in helpers
    3204             :   void CheckPrototypeEnumCache(Node* receiver, Node* receiver_map,
    3205             :                                Label* if_fast, Label* if_slow);
    3206             :   Node* CheckEnumCache(Node* receiver, Label* if_empty, Label* if_runtime);
    3207             : 
    3208             :   TNode<IntPtrT> GetArgumentsLength(CodeStubArguments* args);
    3209             :   TNode<Object> GetArgumentValue(CodeStubArguments* args, TNode<IntPtrT> index);
    3210             : 
    3211             :   // Support for printf-style debugging
    3212             :   void Print(const char* s);
    3213             :   void Print(const char* prefix, Node* tagged_value);
    3214             :   inline void Print(SloppyTNode<Object> tagged_value) {
    3215             :     return Print(nullptr, tagged_value);
    3216             :   }
    3217             :   inline void Print(TNode<MaybeObject> tagged_value) {
    3218             :     return Print(nullptr, tagged_value);
    3219             :   }
    3220             : 
    3221             :   template <class... TArgs>
    3222         504 :   Node* MakeTypeError(MessageTemplate message, Node* context, TArgs... args) {
    3223             :     STATIC_ASSERT(sizeof...(TArgs) <= 3);
    3224        1008 :     Node* const make_type_error = LoadContextElement(
    3225        1512 :         LoadNativeContext(context), Context::MAKE_TYPE_ERROR_INDEX);
    3226             :     return CallJS(CodeFactory::Call(isolate()), context, make_type_error,
    3227         504 :                   UndefinedConstant(), SmiConstant(message), args...);
    3228             :   }
    3229             : 
    3230         224 :   void Abort(AbortReason reason) {
    3231         224 :     CallRuntime(Runtime::kAbort, NoContextConstant(), SmiConstant(reason));
    3232         224 :     Unreachable();
    3233         224 :   }
    3234             : 
    3235          56 :   bool ConstexprBoolNot(bool value) { return !value; }
    3236             : 
    3237         224 :   bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; }
    3238             :   bool ConstexprInt31GreaterThanEqual(int31_t a, int31_t b) { return a >= b; }
    3239         112 :   uint32_t ConstexprUint32Add(uint32_t a, uint32_t b) { return a + b; }
    3240             : 
    3241             :   void PerformStackCheck(TNode<Context> context);
    3242             : 
    3243             :   void SetPropertyLength(TNode<Context> context, TNode<Object> array,
    3244             :                          TNode<Number> length);
    3245             : 
    3246             :   // Checks that {object_map}'s prototype map is the {initial_prototype_map} and
    3247             :   // makes sure that the field with name at index {descriptor} is still
    3248             :   // constant. If it is not, go to label {if_modified}.
    3249             :   //
    3250             :   // To make the checks robust, the method also asserts that the descriptor has
    3251             :   // the right key, the caller must pass the root index of the key
    3252             :   // in {field_name_root_index}.
    3253             :   //
    3254             :   // This is useful for checking that given function has not been patched
    3255             :   // on the prototype.
    3256             :   void GotoIfInitialPrototypePropertyModified(TNode<Map> object_map,
    3257             :                                               TNode<Map> initial_prototype_map,
    3258             :                                               int descfriptor,
    3259             :                                               RootIndex field_name_root_index,
    3260             :                                               Label* if_modified);
    3261             :   struct DescriptorIndexAndName {
    3262        2016 :     DescriptorIndexAndName() {}
    3263        1456 :     DescriptorIndexAndName(int descriptor_index, RootIndex name_root_index)
    3264             :         : descriptor_index(descriptor_index),
    3265        1456 :           name_root_index(name_root_index) {}
    3266             : 
    3267             :     int descriptor_index;
    3268             :     RootIndex name_root_index;
    3269             :   };
    3270             :   void GotoIfInitialPrototypePropertiesModified(
    3271             :       TNode<Map> object_map, TNode<Map> initial_prototype_map,
    3272             :       Vector<DescriptorIndexAndName> properties, Label* if_modified);
    3273             : 
    3274             :   // Implements DescriptorArray::Search().
    3275             :   void DescriptorLookup(SloppyTNode<Name> unique_name,
    3276             :                         SloppyTNode<DescriptorArray> descriptors,
    3277             :                         SloppyTNode<Uint32T> bitfield3, Label* if_found,
    3278             :                         TVariable<IntPtrT>* var_name_index,
    3279             :                         Label* if_not_found);
    3280             : 
    3281             :   // Implements TransitionArray::SearchName() - searches for first transition
    3282             :   // entry with given name (note that there could be multiple entries with
    3283             :   // the same name).
    3284             :   void TransitionLookup(SloppyTNode<Name> unique_name,
    3285             :                         SloppyTNode<TransitionArray> transitions,
    3286             :                         Label* if_found, TVariable<IntPtrT>* var_name_index,
    3287             :                         Label* if_not_found);
    3288             : 
    3289             :   // Implements generic search procedure like i::Search<Array>().
    3290             :   template <typename Array>
    3291             :   void Lookup(TNode<Name> unique_name, TNode<Array> array,
    3292             :               TNode<Uint32T> number_of_valid_entries, Label* if_found,
    3293             :               TVariable<IntPtrT>* var_name_index, Label* if_not_found);
    3294             : 
    3295             :   // Implements generic linear search procedure like i::LinearSearch<Array>().
    3296             :   template <typename Array>
    3297             :   void LookupLinear(TNode<Name> unique_name, TNode<Array> array,
    3298             :                     TNode<Uint32T> number_of_valid_entries, Label* if_found,
    3299             :                     TVariable<IntPtrT>* var_name_index, Label* if_not_found);
    3300             : 
    3301             :   // Implements generic binary search procedure like i::BinarySearch<Array>().
    3302             :   template <typename Array>
    3303             :   void LookupBinary(TNode<Name> unique_name, TNode<Array> array,
    3304             :                     TNode<Uint32T> number_of_valid_entries, Label* if_found,
    3305             :                     TVariable<IntPtrT>* var_name_index, Label* if_not_found);
    3306             : 
    3307             :   // Converts [Descriptor/Transition]Array entry number to a fixed array index.
    3308             :   template <typename Array>
    3309             :   TNode<IntPtrT> EntryIndexToIndex(TNode<Uint32T> entry_index);
    3310             : 
    3311             :   // Implements [Descriptor/Transition]Array::ToKeyIndex.
    3312             :   template <typename Array>
    3313             :   TNode<IntPtrT> ToKeyIndex(TNode<Uint32T> entry_index);
    3314             : 
    3315             :   // Implements [Descriptor/Transition]Array::GetKey.
    3316             :   template <typename Array>
    3317             :   TNode<Name> GetKey(TNode<Array> array, TNode<Uint32T> entry_index);
    3318             : 
    3319             :   // Implements DescriptorArray::GetDetails.
    3320             :   TNode<Uint32T> DescriptorArrayGetDetails(TNode<DescriptorArray> descriptors,
    3321             :                                            TNode<Uint32T> descriptor_number);
    3322             : 
    3323             :   typedef std::function<void(TNode<IntPtrT> descriptor_key_index)>
    3324             :       ForEachDescriptorBodyFunction;
    3325             : 
    3326             :   // Descriptor array accessors based on key_index, which is equal to
    3327             :   // DescriptorArray::ToKeyIndex(descriptor).
    3328             :   TNode<Name> LoadKeyByKeyIndex(TNode<DescriptorArray> container,
    3329             :                                 TNode<IntPtrT> key_index);
    3330             :   TNode<Uint32T> LoadDetailsByKeyIndex(TNode<DescriptorArray> container,
    3331             :                                        TNode<IntPtrT> key_index);
    3332             :   TNode<Object> LoadValueByKeyIndex(TNode<DescriptorArray> container,
    3333             :                                     TNode<IntPtrT> key_index);
    3334             :   TNode<MaybeObject> LoadFieldTypeByKeyIndex(TNode<DescriptorArray> container,
    3335             :                                              TNode<IntPtrT> key_index);
    3336             : 
    3337             :   TNode<IntPtrT> DescriptorEntryToIndex(TNode<IntPtrT> descriptor);
    3338             : 
    3339             :   // Descriptor array accessors based on descriptor.
    3340             :   TNode<Name> LoadKeyByDescriptorEntry(TNode<DescriptorArray> descriptors,
    3341             :                                        TNode<IntPtrT> descriptor);
    3342             :   TNode<Name> LoadKeyByDescriptorEntry(TNode<DescriptorArray> descriptors,
    3343             :                                        int descriptor);
    3344             :   TNode<Uint32T> LoadDetailsByDescriptorEntry(
    3345             :       TNode<DescriptorArray> descriptors, TNode<IntPtrT> descriptor);
    3346             :   TNode<Uint32T> LoadDetailsByDescriptorEntry(
    3347             :       TNode<DescriptorArray> descriptors, int descriptor);
    3348             :   TNode<Object> LoadValueByDescriptorEntry(TNode<DescriptorArray> descriptors,
    3349             :                                            int descriptor);
    3350             :   TNode<MaybeObject> LoadFieldTypeByDescriptorEntry(
    3351             :       TNode<DescriptorArray> descriptors, TNode<IntPtrT> descriptor);
    3352             : 
    3353             :   typedef std::function<void(TNode<Name> key, TNode<Object> value)>
    3354             :       ForEachKeyValueFunction;
    3355             : 
    3356             :   enum ForEachEnumerationMode {
    3357             :     // String and then Symbol properties according to the spec
    3358             :     // ES#sec-object.assign
    3359             :     kEnumerationOrder,
    3360             :     // Order of property addition
    3361             :     kPropertyAdditionOrder,
    3362             :   };
    3363             : 
    3364             :   // For each JSObject property (in DescriptorArray order), check if the key is
    3365             :   // enumerable, and if so, load the value from the receiver and evaluate the
    3366             :   // closure.
    3367             :   void ForEachEnumerableOwnProperty(TNode<Context> context, TNode<Map> map,
    3368             :                                     TNode<JSObject> object,
    3369             :                                     ForEachEnumerationMode mode,
    3370             :                                     const ForEachKeyValueFunction& body,
    3371             :                                     Label* bailout);
    3372             : 
    3373             :   TNode<Object> CallGetterIfAccessor(Node* value, Node* details, Node* context,
    3374             :                                      Node* receiver, Label* if_bailout,
    3375             :                                      GetOwnPropertyMode mode = kCallJSGetter);
    3376             : 
    3377             :   TNode<IntPtrT> TryToIntptr(Node* key, Label* miss);
    3378             : 
    3379             :   void BranchIfPrototypesHaveNoElements(Node* receiver_map,
    3380             :                                         Label* definitely_no_elements,
    3381             :                                         Label* possibly_elements);
    3382             : 
    3383             :   void InitializeFunctionContext(Node* native_context, Node* context,
    3384             :                                  int slots);
    3385             : 
    3386             :   TNode<JSArray> ArrayCreate(TNode<Context> context, TNode<Number> length);
    3387             : 
    3388             :   // Allocate a clone of a mutable primitive, if {object} is a
    3389             :   // MutableHeapNumber.
    3390             :   TNode<Object> CloneIfMutablePrimitive(TNode<Object> object);
    3391             : 
    3392             :  private:
    3393             :   friend class CodeStubArguments;
    3394             : 
    3395             :   void HandleBreakOnNode();
    3396             : 
    3397             :   TNode<HeapObject> AllocateRawDoubleAligned(TNode<IntPtrT> size_in_bytes,
    3398             :                                              AllocationFlags flags,
    3399             :                                              TNode<RawPtrT> top_address,
    3400             :                                              TNode<RawPtrT> limit_address);
    3401             :   TNode<HeapObject> AllocateRawUnaligned(TNode<IntPtrT> size_in_bytes,
    3402             :                                          AllocationFlags flags,
    3403             :                                          TNode<RawPtrT> top_address,
    3404             :                                          TNode<RawPtrT> limit_address);
    3405             :   TNode<HeapObject> AllocateRaw(TNode<IntPtrT> size_in_bytes,
    3406             :                                 AllocationFlags flags,
    3407             :                                 TNode<RawPtrT> top_address,
    3408             :                                 TNode<RawPtrT> limit_address);
    3409             : 
    3410             :   // Allocate and return a JSArray of given total size in bytes with header
    3411             :   // fields initialized.
    3412             :   TNode<JSArray> AllocateUninitializedJSArray(TNode<Map> array_map,
    3413             :                                               TNode<Smi> length,
    3414             :                                               Node* allocation_site,
    3415             :                                               TNode<IntPtrT> size_in_bytes);
    3416             : 
    3417             :   TNode<BoolT> IsValidSmi(TNode<Smi> smi);
    3418             :   Node* SmiShiftBitsConstant();
    3419             : 
    3420             :   // Emits keyed sloppy arguments load if the |value| is nullptr or store
    3421             :   // otherwise. Returns either the loaded value or |value|.
    3422             :   Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
    3423             :                                  Label* bailout,
    3424             :                                  ArgumentsAccessMode access_mode);
    3425             : 
    3426             :   TNode<String> AllocateSlicedString(RootIndex map_root_index,
    3427             :                                      TNode<Uint32T> length,
    3428             :                                      TNode<String> parent, TNode<Smi> offset);
    3429             : 
    3430             :   // Allocate a MutableHeapNumber without initializing its value.
    3431             :   TNode<MutableHeapNumber> AllocateMutableHeapNumber();
    3432             : 
    3433             :   Node* SelectImpl(TNode<BoolT> condition, const NodeGenerator& true_body,
    3434             :                    const NodeGenerator& false_body, MachineRepresentation rep);
    3435             : 
    3436             :   // Implements [Descriptor/Transition]Array::number_of_entries.
    3437             :   template <typename Array>
    3438             :   TNode<Uint32T> NumberOfEntries(TNode<Array> array);
    3439             : 
    3440             :   // Implements [Descriptor/Transition]Array::GetSortedKeyIndex.
    3441             :   template <typename Array>
    3442             :   TNode<Uint32T> GetSortedKeyIndex(TNode<Array> descriptors,
    3443             :                                    TNode<Uint32T> entry_index);
    3444             : 
    3445             :   TNode<Smi> CollectFeedbackForString(SloppyTNode<Int32T> instance_type);
    3446             :   void GenerateEqual_Same(Node* value, Label* if_equal, Label* if_notequal,
    3447             :                           Variable* var_type_feedback = nullptr);
    3448             :   TNode<String> AllocAndCopyStringCharacters(Node* from,
    3449             :                                              Node* from_instance_type,
    3450             :                                              TNode<IntPtrT> from_index,
    3451             :                                              TNode<IntPtrT> character_count);
    3452             : 
    3453             :   static const int kElementLoopUnrollThreshold = 8;
    3454             : 
    3455             :   // {convert_bigint} is only meaningful when {mode} == kToNumber.
    3456             :   Node* NonNumberToNumberOrNumeric(
    3457             :       Node* context, Node* input, Object::Conversion mode,
    3458             :       BigIntHandling bigint_handling = BigIntHandling::kThrow);
    3459             : 
    3460             :   void TaggedToNumeric(Node* context, Node* value, Label* done,
    3461             :                        Variable* var_numeric, Variable* var_feedback);
    3462             : 
    3463             :   template <Object::Conversion conversion>
    3464             :   void TaggedToWord32OrBigIntImpl(Node* context, Node* value, Label* if_number,
    3465             :                                   Variable* var_word32,
    3466             :                                   Label* if_bigint = nullptr,
    3467             :                                   Variable* var_bigint = nullptr,
    3468             :                                   Variable* var_feedback = nullptr);
    3469             : 
    3470             :  private:
    3471             :   // Low-level accessors for Descriptor arrays.
    3472             :   TNode<MaybeObject> LoadDescriptorArrayElement(TNode<DescriptorArray> object,
    3473             :                                                 Node* index,
    3474             :                                                 int additional_offset = 0);
    3475             : };
    3476             : 
    3477             : class CodeStubArguments {
    3478             :  public:
    3479             :   typedef compiler::Node Node;
    3480             :   template <class T>
    3481             :   using TNode = compiler::TNode<T>;
    3482             :   template <class T>
    3483             :   using SloppyTNode = compiler::SloppyTNode<T>;
    3484             :   enum ReceiverMode { kHasReceiver, kNoReceiver };
    3485             : 
    3486             :   // |argc| is an intptr value which specifies the number of arguments passed
    3487             :   // to the builtin excluding the receiver. The arguments will include a
    3488             :   // receiver iff |receiver_mode| is kHasReceiver.
    3489        7448 :   CodeStubArguments(CodeStubAssembler* assembler, Node* argc,
    3490             :                     ReceiverMode receiver_mode = ReceiverMode::kHasReceiver)
    3491             :       : CodeStubArguments(assembler, argc, nullptr,
    3492        7492 :                           CodeStubAssembler::INTPTR_PARAMETERS, receiver_mode) {
    3493        7448 :   }
    3494             : 
    3495             :   // |argc| is either a smi or intptr depending on |param_mode|. The arguments
    3496             :   // include a receiver iff |receiver_mode| is kHasReceiver.
    3497             :   CodeStubArguments(CodeStubAssembler* assembler, Node* argc, Node* fp,
    3498             :                     CodeStubAssembler::ParameterMode param_mode,
    3499             :                     ReceiverMode receiver_mode = ReceiverMode::kHasReceiver);
    3500             : 
    3501             :   TNode<Object> GetReceiver() const;
    3502             :   // Replaces receiver argument on the expression stack. Should be used only
    3503             :   // for manipulating arguments in trampoline builtins before tail calling
    3504             :   // further with passing all the JS arguments as is.
    3505             :   void SetReceiver(TNode<Object> object) const;
    3506             : 
    3507             :   // Computes address of the index'th argument.
    3508             :   TNode<WordT> AtIndexPtr(Node* index,
    3509             :                           CodeStubAssembler::ParameterMode mode =
    3510             :                               CodeStubAssembler::INTPTR_PARAMETERS) const;
    3511             : 
    3512             :   // |index| is zero-based and does not include the receiver
    3513             :   TNode<Object> AtIndex(Node* index,
    3514             :                         CodeStubAssembler::ParameterMode mode =
    3515             :                             CodeStubAssembler::INTPTR_PARAMETERS) const;
    3516             : 
    3517             :   TNode<Object> AtIndex(int index) const;
    3518             : 
    3519        2800 :   TNode<Object> GetOptionalArgumentValue(int index) {
    3520        2800 :     return GetOptionalArgumentValue(index, assembler_->UndefinedConstant());
    3521             :   }
    3522             :   TNode<Object> GetOptionalArgumentValue(int index,
    3523             :                                          TNode<Object> default_value);
    3524             : 
    3525         316 :   Node* GetLength(CodeStubAssembler::ParameterMode mode) const {
    3526             :     DCHECK_EQ(mode, argc_mode_);
    3527         316 :     return argc_;
    3528             :   }
    3529             : 
    3530        7672 :   TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index) {
    3531        7672 :     return GetOptionalArgumentValue(index, assembler_->UndefinedConstant());
    3532             :   }
    3533             :   TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index,
    3534             :                                          TNode<Object> default_value);
    3535        4536 :   TNode<IntPtrT> GetLength() const {
    3536             :     DCHECK_EQ(argc_mode_, CodeStubAssembler::INTPTR_PARAMETERS);
    3537        4536 :     return assembler_->UncheckedCast<IntPtrT>(argc_);
    3538             :   }
    3539             : 
    3540             :   typedef std::function<void(Node* arg)> ForEachBodyFunction;
    3541             : 
    3542             :   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
    3543         112 :   void ForEach(const ForEachBodyFunction& body, Node* first = nullptr,
    3544             :                Node* last = nullptr,
    3545             :                CodeStubAssembler::ParameterMode mode =
    3546             :                    CodeStubAssembler::INTPTR_PARAMETERS) {
    3547         224 :     CodeStubAssembler::VariableList list(0, assembler_->zone());
    3548         112 :     ForEach(list, body, first, last);
    3549         112 :   }
    3550             : 
    3551             :   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
    3552             :   void ForEach(const CodeStubAssembler::VariableList& vars,
    3553             :                const ForEachBodyFunction& body, Node* first = nullptr,
    3554             :                Node* last = nullptr,
    3555             :                CodeStubAssembler::ParameterMode mode =
    3556             :                    CodeStubAssembler::INTPTR_PARAMETERS);
    3557             : 
    3558             :   void PopAndReturn(Node* value);
    3559             : 
    3560             :  private:
    3561             :   Node* GetArguments();
    3562             : 
    3563             :   CodeStubAssembler* assembler_;
    3564             :   CodeStubAssembler::ParameterMode argc_mode_;
    3565             :   ReceiverMode receiver_mode_;
    3566             :   Node* argc_;
    3567             :   TNode<WordT> arguments_;
    3568             :   Node* fp_;
    3569             : };
    3570             : 
    3571        4704 : class ToDirectStringAssembler : public CodeStubAssembler {
    3572             :  private:
    3573             :   enum StringPointerKind { PTR_TO_DATA, PTR_TO_STRING };
    3574             : 
    3575             :  public:
    3576             :   enum Flag {
    3577             :     kDontUnpackSlicedStrings = 1 << 0,
    3578             :   };
    3579             :   typedef base::Flags<Flag> Flags;
    3580             : 
    3581             :   ToDirectStringAssembler(compiler::CodeAssemblerState* state, Node* string,
    3582             :                           Flags flags = Flags());
    3583             : 
    3584             :   // Converts flat cons, thin, and sliced strings and returns the direct
    3585             :   // string. The result can be either a sequential or external string.
    3586             :   // Jumps to if_bailout if the string if the string is indirect and cannot
    3587             :   // be unpacked.
    3588             :   TNode<String> TryToDirect(Label* if_bailout);
    3589             : 
    3590             :   // Returns a pointer to the beginning of the string data.
    3591             :   // Jumps to if_bailout if the external string cannot be unpacked.
    3592        4256 :   TNode<RawPtrT> PointerToData(Label* if_bailout) {
    3593        4256 :     return TryToSequential(PTR_TO_DATA, if_bailout);
    3594             :   }
    3595             : 
    3596             :   // Returns a pointer that, offset-wise, looks like a String.
    3597             :   // Jumps to if_bailout if the external string cannot be unpacked.
    3598         448 :   TNode<RawPtrT> PointerToString(Label* if_bailout) {
    3599         448 :     return TryToSequential(PTR_TO_STRING, if_bailout);
    3600             :   }
    3601             : 
    3602          56 :   Node* string() { return var_string_.value(); }
    3603        4872 :   Node* instance_type() { return var_instance_type_.value(); }
    3604        4984 :   TNode<IntPtrT> offset() {
    3605        4984 :     return UncheckedCast<IntPtrT>(var_offset_.value());
    3606             :   }
    3607        5152 :   Node* is_external() { return var_is_external_.value(); }
    3608             : 
    3609             :  private:
    3610             :   TNode<RawPtrT> TryToSequential(StringPointerKind ptr_kind, Label* if_bailout);
    3611             : 
    3612             :   Variable var_string_;
    3613             :   Variable var_instance_type_;
    3614             :   Variable var_offset_;
    3615             :   Variable var_is_external_;
    3616             : 
    3617             :   const Flags flags_;
    3618             : };
    3619             : 
    3620        5308 : DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags)
    3621             : 
    3622             : }  // namespace internal
    3623             : }  // namespace v8
    3624             : #endif  // V8_CODE_STUB_ASSEMBLER_H_

Generated by: LCOV version 1.10