LCOV - code coverage report
Current view: top level - src - code-stub-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 426 427 99.8 %
Date: 2019-02-19 Functions: 567 590 96.1 %

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

Generated by: LCOV version 1.10