LCOV - code coverage report
Current view: top level - src - code-stub-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 112 113 99.1 %
Date: 2017-04-26 Functions: 55 55 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_CODE_STUB_ASSEMBLER_H_
       6             : #define V8_CODE_STUB_ASSEMBLER_H_
       7             : 
       8             : #include <functional>
       9             : 
      10             : #include "src/compiler/code-assembler.h"
      11             : #include "src/globals.h"
      12             : #include "src/objects.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : class CallInterfaceDescriptor;
      18             : class CodeStubArguments;
      19             : class StatsCounter;
      20             : class StubCache;
      21             : 
      22             : enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
      23             : 
      24             : #define HEAP_CONSTANT_LIST(V)                         \
      25             :   V(AccessorInfoMap, AccessorInfoMap)                 \
      26             :   V(AccessorPairMap, AccessorPairMap)                 \
      27             :   V(AllocationSiteMap, AllocationSiteMap)             \
      28             :   V(BooleanMap, BooleanMap)                           \
      29             :   V(CodeMap, CodeMap)                                 \
      30             :   V(empty_string, EmptyString)                        \
      31             :   V(EmptyFixedArray, EmptyFixedArray)                 \
      32             :   V(FalseValue, False)                                \
      33             :   V(FixedArrayMap, FixedArrayMap)                     \
      34             :   V(FixedCOWArrayMap, FixedCOWArrayMap)               \
      35             :   V(FixedDoubleArrayMap, FixedDoubleArrayMap)         \
      36             :   V(FunctionTemplateInfoMap, FunctionTemplateInfoMap) \
      37             :   V(has_instance_symbol, HasInstanceSymbol)           \
      38             :   V(HeapNumberMap, HeapNumberMap)                     \
      39             :   V(NoClosuresCellMap, NoClosuresCellMap)             \
      40             :   V(OneClosureCellMap, OneClosureCellMap)             \
      41             :   V(ManyClosuresCellMap, ManyClosuresCellMap)         \
      42             :   V(MinusZeroValue, MinusZero)                        \
      43             :   V(NanValue, Nan)                                    \
      44             :   V(NullValue, Null)                                  \
      45             :   V(GlobalPropertyCellMap, PropertyCellMap)           \
      46             :   V(SymbolMap, SymbolMap)                             \
      47             :   V(TheHoleValue, TheHole)                            \
      48             :   V(TrueValue, True)                                  \
      49             :   V(Tuple2Map, Tuple2Map)                             \
      50             :   V(Tuple3Map, Tuple3Map)                             \
      51             :   V(UndefinedValue, Undefined)                        \
      52             :   V(WeakCellMap, WeakCellMap)
      53             : 
      54             : // Provides JavaScript-specific "macro-assembler" functionality on top of the
      55             : // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
      56             : // it's possible to add JavaScript-specific useful CodeAssembler "macros"
      57             : // without modifying files in the compiler directory (and requiring a review
      58             : // from a compiler directory OWNER).
      59      118855 : class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
      60             :  public:
      61             :   typedef compiler::Node Node;
      62             : 
      63             :   CodeStubAssembler(compiler::CodeAssemblerState* state);
      64             : 
      65             :   enum AllocationFlag : uint8_t {
      66             :     kNone = 0,
      67             :     kDoubleAlignment = 1,
      68             :     kPretenured = 1 << 1,
      69             :     kAllowLargeObjectAllocation = 1 << 2,
      70             :   };
      71             : 
      72             :   typedef base::Flags<AllocationFlag> AllocationFlags;
      73             : 
      74             :   enum ParameterMode { SMI_PARAMETERS, INTPTR_PARAMETERS };
      75             : 
      76             :   // On 32-bit platforms, there is a slight performance advantage to doing all
      77             :   // of the array offset/index arithmetic with SMIs, since it's possible
      78             :   // to save a few tag/untag operations without paying an extra expense when
      79             :   // calculating array offset (the smi math can be folded away) and there are
      80             :   // fewer live ranges. Thus only convert indices to untagged value on 64-bit
      81             :   // platforms.
      82             :   ParameterMode OptimalParameterMode() const {
      83        4993 :     return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS;
      84             :   }
      85             : 
      86             :   MachineRepresentation ParameterRepresentation(ParameterMode mode) const {
      87             :     return mode == INTPTR_PARAMETERS ? MachineType::PointerRepresentation()
      88         923 :                                      : MachineRepresentation::kTaggedSigned;
      89             :   }
      90             : 
      91             :   MachineRepresentation OptimalParameterRepresentation() const {
      92             :     return ParameterRepresentation(OptimalParameterMode());
      93             :   }
      94             : 
      95             :   Node* ParameterToWord(Node* value, ParameterMode mode) {
      96        1376 :     if (mode == SMI_PARAMETERS) value = SmiUntag(value);
      97             :     return value;
      98             :   }
      99             : 
     100             :   Node* WordToParameter(Node* value, ParameterMode mode) {
     101         192 :     if (mode == SMI_PARAMETERS) value = SmiTag(value);
     102             :     return value;
     103             :   }
     104             : 
     105             :   Node* ParameterToTagged(Node* value, ParameterMode mode) {
     106       17411 :     if (mode != SMI_PARAMETERS) value = SmiTag(value);
     107             :     return value;
     108             :   }
     109             : 
     110             :   Node* TaggedToParameter(Node* value, ParameterMode mode) {
     111       12094 :     if (mode != SMI_PARAMETERS) value = SmiUntag(value);
     112             :     return value;
     113             :   }
     114             : 
     115             : #define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName) \
     116             :   Node* OpName(Node* a, Node* b, ParameterMode mode) {   \
     117             :     if (mode == SMI_PARAMETERS) {                        \
     118             :       return SmiOpName(a, b);                            \
     119             :     } else {                                             \
     120             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);                \
     121             :       return IntPtrOpName(a, b);                         \
     122             :     }                                                    \
     123             :   }
     124          86 :   PARAMETER_BINOP(IntPtrOrSmiMin, IntPtrMin, SmiMin)
     125       40405 :   PARAMETER_BINOP(IntPtrOrSmiAdd, IntPtrAdd, SmiAdd)
     126         602 :   PARAMETER_BINOP(IntPtrOrSmiSub, IntPtrSub, SmiSub)
     127             :   PARAMETER_BINOP(IntPtrOrSmiLessThan, IntPtrLessThan, SmiLessThan)
     128          86 :   PARAMETER_BINOP(IntPtrOrSmiLessThanOrEqual, IntPtrLessThanOrEqual,
     129             :                   SmiLessThanOrEqual)
     130         923 :   PARAMETER_BINOP(IntPtrOrSmiGreaterThan, IntPtrGreaterThan, SmiGreaterThan)
     131             :   PARAMETER_BINOP(IntPtrOrSmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual,
     132             :                   SmiGreaterThanOrEqual)
     133          43 :   PARAMETER_BINOP(UintPtrOrSmiLessThan, UintPtrLessThan, SmiBelow)
     134        4809 :   PARAMETER_BINOP(UintPtrOrSmiGreaterThanOrEqual, UintPtrGreaterThanOrEqual,
     135             :                   SmiAboveOrEqual)
     136             : #undef PARAMETER_BINOP
     137             : 
     138             :   Node* NoContextConstant();
     139             : #define HEAP_CONSTANT_ACCESSOR(rootName, name) Node* name##Constant();
     140             :   HEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR)
     141             : #undef HEAP_CONSTANT_ACCESSOR
     142             : 
     143             : #define HEAP_CONSTANT_TEST(rootName, name) Node* Is##name(Node* value);
     144             :   HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST)
     145             : #undef HEAP_CONSTANT_TEST
     146             : 
     147             :   Node* HashSeed();
     148             :   Node* StaleRegisterConstant();
     149             : 
     150             :   Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
     151             : 
     152             :   bool IsIntPtrOrSmiConstantZero(Node* test);
     153             : 
     154             :   // Round the 32bits payload of the provided word up to the next power of two.
     155             :   Node* IntPtrRoundUpToPowerOfTwo32(Node* value);
     156             :   // Select the maximum of the two provided IntPtr values.
     157             :   Node* IntPtrMax(Node* left, Node* right);
     158             :   // Select the minimum of the two provided IntPtr values.
     159             :   Node* IntPtrMin(Node* left, Node* right);
     160             : 
     161             :   // Float64 operations.
     162             :   Node* Float64Ceil(Node* x);
     163             :   Node* Float64Floor(Node* x);
     164             :   Node* Float64Round(Node* x);
     165             :   Node* Float64RoundToEven(Node* x);
     166             :   Node* Float64Trunc(Node* x);
     167             : 
     168             :   // Tag a Word as a Smi value.
     169             :   Node* SmiTag(Node* value);
     170             :   // Untag a Smi value as a Word.
     171             :   Node* SmiUntag(Node* value);
     172             : 
     173             :   // Smi conversions.
     174             :   Node* SmiToFloat64(Node* value);
     175        3748 :   Node* SmiFromWord(Node* value) { return SmiTag(value); }
     176             :   Node* SmiFromWord32(Node* value);
     177        3612 :   Node* SmiToWord(Node* value) { return SmiUntag(value); }
     178             :   Node* SmiToWord32(Node* value);
     179             : 
     180             :   // Smi operations.
     181             : #define SMI_ARITHMETIC_BINOP(SmiOpName, IntPtrOpName)                  \
     182             :   Node* SmiOpName(Node* a, Node* b) {                                  \
     183             :     return BitcastWordToTaggedSigned(                                  \
     184             :         IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b))); \
     185             :   }
     186       35343 :   SMI_ARITHMETIC_BINOP(SmiAdd, IntPtrAdd)
     187        2084 :   SMI_ARITHMETIC_BINOP(SmiSub, IntPtrSub)
     188         430 :   SMI_ARITHMETIC_BINOP(SmiAnd, WordAnd)
     189       15480 :   SMI_ARITHMETIC_BINOP(SmiOr, WordOr)
     190             : #undef SMI_ARITHMETIC_BINOP
     191             : 
     192        1290 :   Node* SmiShl(Node* a, int shift) {
     193        1290 :     return BitcastWordToTaggedSigned(WordShl(BitcastTaggedToWord(a), shift));
     194             :   }
     195             : 
     196         910 :   Node* SmiShr(Node* a, int shift) {
     197             :     return BitcastWordToTaggedSigned(
     198             :         WordAnd(WordShr(BitcastTaggedToWord(a), shift),
     199         910 :                 BitcastTaggedToWord(SmiConstant(-1))));
     200             :   }
     201             : 
     202             :   Node* WordOrSmiShl(Node* a, int shift, ParameterMode mode) {
     203             :     if (mode == SMI_PARAMETERS) {
     204             :       return SmiShl(a, shift);
     205             :     } else {
     206             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);
     207             :       return WordShl(a, shift);
     208             :     }
     209             :   }
     210             : 
     211        2040 :   Node* WordOrSmiShr(Node* a, int shift, ParameterMode mode) {
     212        2040 :     if (mode == SMI_PARAMETERS) {
     213           7 :       return SmiShr(a, shift);
     214             :     } else {
     215             :       DCHECK_EQ(INTPTR_PARAMETERS, mode);
     216        2033 :       return WordShr(a, shift);
     217             :     }
     218             :   }
     219             : 
     220             : #define SMI_COMPARISON_OP(SmiOpName, IntPtrOpName)                       \
     221             :   Node* SmiOpName(Node* a, Node* b) {                                    \
     222             :     return IntPtrOpName(BitcastTaggedToWord(a), BitcastTaggedToWord(b)); \
     223             :   }
     224        6966 :   SMI_COMPARISON_OP(SmiEqual, WordEqual)
     225         129 :   SMI_COMPARISON_OP(SmiNotEqual, WordNotEqual)
     226        3053 :   SMI_COMPARISON_OP(SmiAbove, UintPtrGreaterThan)
     227        1720 :   SMI_COMPARISON_OP(SmiAboveOrEqual, UintPtrGreaterThanOrEqual)
     228         516 :   SMI_COMPARISON_OP(SmiBelow, UintPtrLessThan)
     229        4171 :   SMI_COMPARISON_OP(SmiLessThan, IntPtrLessThan)
     230        1118 :   SMI_COMPARISON_OP(SmiLessThanOrEqual, IntPtrLessThanOrEqual)
     231         559 :   SMI_COMPARISON_OP(SmiGreaterThan, IntPtrGreaterThan)
     232        1763 :   SMI_COMPARISON_OP(SmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual)
     233             : #undef SMI_COMPARISON_OP
     234             :   Node* SmiMax(Node* a, Node* b);
     235             :   Node* SmiMin(Node* a, Node* b);
     236             :   // Computes a % b for Smi inputs a and b; result is not necessarily a Smi.
     237             :   Node* SmiMod(Node* a, Node* b);
     238             :   // Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
     239             :   Node* SmiMul(Node* a, Node* b);
     240             :   // Tries to computes dividend / divisor for Smi inputs; branching to bailout
     241             :   // if the division needs to be performed as a floating point operation.
     242             :   Node* TrySmiDiv(Node* dividend, Node* divisor, Label* bailout);
     243             : 
     244             :   // Smi | HeapNumber operations.
     245             :   Node* NumberInc(Node* value);
     246             :   Node* NumberDec(Node* value);
     247             :   void GotoIfNotNumber(Node* value, Label* is_not_number);
     248             :   void GotoIfNumber(Node* value, Label* is_number);
     249             : 
     250             :   // Allocate an object of the given size.
     251             :   Node* AllocateInNewSpace(Node* size, AllocationFlags flags = kNone);
     252             :   Node* AllocateInNewSpace(int size, AllocationFlags flags = kNone);
     253             :   Node* Allocate(Node* size, AllocationFlags flags = kNone);
     254             :   Node* Allocate(int size, AllocationFlags flags = kNone);
     255             :   Node* InnerAllocate(Node* previous, int offset);
     256             :   Node* InnerAllocate(Node* previous, Node* offset);
     257             :   Node* IsRegularHeapObjectSize(Node* size);
     258             : 
     259             :   typedef std::function<Node*()> NodeGenerator;
     260             : 
     261             :   void Assert(const NodeGenerator& condition_body, const char* string = nullptr,
     262             :               const char* file = nullptr, int line = 0);
     263             : 
     264             :   Node* Select(Node* condition, const NodeGenerator& true_body,
     265             :                const NodeGenerator& false_body, MachineRepresentation rep);
     266             : 
     267             :   Node* SelectConstant(Node* condition, Node* true_value, Node* false_value,
     268             :                        MachineRepresentation rep);
     269             : 
     270             :   Node* SelectInt32Constant(Node* condition, int true_value, int false_value);
     271             :   Node* SelectIntPtrConstant(Node* condition, int true_value, int false_value);
     272             :   Node* SelectBooleanConstant(Node* condition);
     273             :   Node* SelectTaggedConstant(Node* condition, Node* true_value,
     274             :                              Node* false_value);
     275             :   Node* SelectSmiConstant(Node* condition, Smi* true_value, Smi* false_value);
     276             :   Node* SelectSmiConstant(Node* condition, int true_value, Smi* false_value) {
     277             :     return SelectSmiConstant(condition, Smi::FromInt(true_value), false_value);
     278             :   }
     279             :   Node* SelectSmiConstant(Node* condition, Smi* true_value, int false_value) {
     280             :     return SelectSmiConstant(condition, true_value, Smi::FromInt(false_value));
     281             :   }
     282             :   Node* SelectSmiConstant(Node* condition, int true_value, int false_value) {
     283             :     return SelectSmiConstant(condition, Smi::FromInt(true_value),
     284        2666 :                              Smi::FromInt(false_value));
     285             :   }
     286             : 
     287             :   Node* TruncateWordToWord32(Node* value);
     288             : 
     289             :   // Check a value for smi-ness
     290             :   Node* TaggedIsSmi(Node* a);
     291             :   Node* TaggedIsNotSmi(Node* a);
     292             :   // Check that the value is a non-negative smi.
     293             :   Node* TaggedIsPositiveSmi(Node* a);
     294             :   // Check that a word has a word-aligned address.
     295             :   Node* WordIsWordAligned(Node* word);
     296             :   Node* WordIsPowerOfTwo(Node* value);
     297             : 
     298        2365 :   void BranchIfSmiEqual(Node* a, Node* b, Label* if_true, Label* if_false) {
     299        2365 :     Branch(SmiEqual(a, b), if_true, if_false);
     300        2365 :   }
     301             : 
     302         860 :   void BranchIfSmiLessThan(Node* a, Node* b, Label* if_true, Label* if_false) {
     303         860 :     Branch(SmiLessThan(a, b), if_true, if_false);
     304         860 :   }
     305             : 
     306         430 :   void BranchIfSmiLessThanOrEqual(Node* a, Node* b, Label* if_true,
     307             :                                   Label* if_false) {
     308         430 :     Branch(SmiLessThanOrEqual(a, b), if_true, if_false);
     309         430 :   }
     310             : 
     311        1892 :   void BranchIfFloat64IsNaN(Node* value, Label* if_true, Label* if_false) {
     312        1892 :     Branch(Float64Equal(value, value), if_false, if_true);
     313        1892 :   }
     314             : 
     315             :   // Branches to {if_true} if ToBoolean applied to {value} yields true,
     316             :   // otherwise goes to {if_false}.
     317             :   void BranchIfToBooleanIsTrue(Node* value, Label* if_true, Label* if_false);
     318             : 
     319             :   void BranchIfJSReceiver(Node* object, Label* if_true, Label* if_false);
     320             :   void BranchIfJSObject(Node* object, Label* if_true, Label* if_false);
     321             : 
     322             :   enum class FastJSArrayAccessMode { INBOUNDS_READ, ANY_ACCESS };
     323             :   void BranchIfFastJSArray(Node* object, Node* context,
     324             :                            FastJSArrayAccessMode mode, Label* if_true,
     325             :                            Label* if_false);
     326             : 
     327             :   // Load value from current frame by given offset in bytes.
     328             :   Node* LoadFromFrame(int offset, MachineType rep = MachineType::AnyTagged());
     329             :   // Load value from current parent frame by given offset in bytes.
     330             :   Node* LoadFromParentFrame(int offset,
     331             :                             MachineType rep = MachineType::AnyTagged());
     332             : 
     333             :   // Load an object pointer from a buffer that isn't in the heap.
     334             :   Node* LoadBufferObject(Node* buffer, int offset,
     335             :                          MachineType rep = MachineType::AnyTagged());
     336             :   // Load a field from an object on the heap.
     337             :   Node* LoadObjectField(Node* object, int offset,
     338             :                         MachineType rep = MachineType::AnyTagged());
     339             :   Node* LoadObjectField(Node* object, Node* offset,
     340             :                         MachineType rep = MachineType::AnyTagged());
     341             :   // Load a SMI field and untag it.
     342             :   Node* LoadAndUntagObjectField(Node* object, int offset);
     343             :   // Load a SMI field, untag it, and convert to Word32.
     344             :   Node* LoadAndUntagToWord32ObjectField(Node* object, int offset);
     345             :   // Load a SMI and untag it.
     346             :   Node* LoadAndUntagSmi(Node* base, int index);
     347             :   // Load a SMI root, untag it, and convert to Word32.
     348             :   Node* LoadAndUntagToWord32Root(Heap::RootListIndex root_index);
     349             : 
     350             :   // Tag a smi and store it.
     351             :   Node* StoreAndTagSmi(Node* base, int offset, Node* value);
     352             : 
     353             :   // Load the floating point value of a HeapNumber.
     354             :   Node* LoadHeapNumberValue(Node* object);
     355             :   // Load the Map of an HeapObject.
     356             :   Node* LoadMap(Node* object);
     357             :   // Load the instance type of an HeapObject.
     358             :   Node* LoadInstanceType(Node* object);
     359             :   // Compare the instance the type of the object against the provided one.
     360             :   Node* HasInstanceType(Node* object, InstanceType type);
     361             :   Node* DoesntHaveInstanceType(Node* object, InstanceType type);
     362             :   // Load the properties backing store of a JSObject.
     363             :   Node* LoadProperties(Node* object);
     364             :   // Load the elements backing store of a JSObject.
     365             :   Node* LoadElements(Node* object);
     366             :   // Load the length of a JSArray instance.
     367             :   Node* LoadJSArrayLength(Node* array);
     368             :   // Load the length of a fixed array base instance.
     369             :   Node* LoadFixedArrayBaseLength(Node* array);
     370             :   // Load the length of a fixed array base instance.
     371             :   Node* LoadAndUntagFixedArrayBaseLength(Node* array);
     372             :   // Load the bit field of a Map.
     373             :   Node* LoadMapBitField(Node* map);
     374             :   // Load bit field 2 of a map.
     375             :   Node* LoadMapBitField2(Node* map);
     376             :   // Load bit field 3 of a map.
     377             :   Node* LoadMapBitField3(Node* map);
     378             :   // Load the instance type of a map.
     379             :   Node* LoadMapInstanceType(Node* map);
     380             :   // Load the ElementsKind of a map.
     381             :   Node* LoadMapElementsKind(Node* map);
     382             :   // Load the instance descriptors of a map.
     383             :   Node* LoadMapDescriptors(Node* map);
     384             :   // Load the prototype of a map.
     385             :   Node* LoadMapPrototype(Node* map);
     386             :   // Load the prototype info of a map. The result has to be checked if it is a
     387             :   // prototype info object or not.
     388             :   Node* LoadMapPrototypeInfo(Node* map, Label* if_has_no_proto_info);
     389             :   // Load the instance size of a Map.
     390             :   Node* LoadMapInstanceSize(Node* map);
     391             :   // Load the inobject properties count of a Map (valid only for JSObjects).
     392             :   Node* LoadMapInobjectProperties(Node* map);
     393             :   // Load the constructor function index of a Map (only for primitive maps).
     394             :   Node* LoadMapConstructorFunctionIndex(Node* map);
     395             :   // Load the constructor of a Map (equivalent to
     396             :   // Map::GetConstructor()).
     397             :   Node* LoadMapConstructor(Node* map);
     398             :   // Loads a value from the specially encoded integer fields in the
     399             :   // SharedFunctionInfo object.
     400             :   // TODO(danno): This currently only works for the integer fields that are
     401             :   // mapped to the upper part of 64-bit words. We should customize
     402             :   // SFI::BodyDescriptor and store int32 values directly.
     403             :   Node* LoadSharedFunctionInfoSpecialField(Node* shared, int offset,
     404             :                                            ParameterMode param_mode);
     405             : 
     406             :   // Check if the map is set for slow properties.
     407             :   Node* IsDictionaryMap(Node* map);
     408             : 
     409             :   // Load the hash field of a name as an uint32 value.
     410             :   Node* LoadNameHashField(Node* name);
     411             :   // Load the hash value of a name as an uint32 value.
     412             :   // If {if_hash_not_computed} label is specified then it also checks if
     413             :   // hash is actually computed.
     414             :   Node* LoadNameHash(Node* name, Label* if_hash_not_computed = nullptr);
     415             : 
     416             :   // Load length field of a String object.
     417             :   Node* LoadStringLength(Node* object);
     418             :   // Load value field of a JSValue object.
     419             :   Node* LoadJSValueValue(Node* object);
     420             :   // Load value field of a WeakCell object.
     421             :   Node* LoadWeakCellValueUnchecked(Node* weak_cell);
     422             :   Node* LoadWeakCellValue(Node* weak_cell, Label* if_cleared = nullptr);
     423             : 
     424             :   // Load an array element from a FixedArray.
     425             :   Node* LoadFixedArrayElement(Node* object, Node* index,
     426             :                               int additional_offset = 0,
     427             :                               ParameterMode parameter_mode = INTPTR_PARAMETERS);
     428       33010 :   Node* LoadFixedArrayElement(Node* object, int index,
     429             :                               int additional_offset = 0) {
     430             :     return LoadFixedArrayElement(object, IntPtrConstant(index),
     431       33010 :                                  additional_offset);
     432             :   }
     433             :   // Load an array element from a FixedArray, untag it and return it as Word32.
     434             :   Node* LoadAndUntagToWord32FixedArrayElement(
     435             :       Node* object, Node* index, int additional_offset = 0,
     436             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
     437             :   // Load an array element from a FixedDoubleArray.
     438             :   Node* LoadFixedDoubleArrayElement(
     439             :       Node* object, Node* index, MachineType machine_type,
     440             :       int additional_offset = 0,
     441             :       ParameterMode parameter_mode = INTPTR_PARAMETERS,
     442             :       Label* if_hole = nullptr);
     443             : 
     444             :   // Load Float64 value by |base| + |offset| address. If the value is a double
     445             :   // hole then jump to |if_hole|. If |machine_type| is None then only the hole
     446             :   // check is generated.
     447             :   Node* LoadDoubleWithHoleCheck(
     448             :       Node* base, Node* offset, Label* if_hole,
     449             :       MachineType machine_type = MachineType::Float64());
     450             :   Node* LoadFixedTypedArrayElement(
     451             :       Node* data_pointer, Node* index_node, ElementsKind elements_kind,
     452             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
     453             :   Node* LoadFixedTypedArrayElementAsTagged(
     454             :       Node* data_pointer, Node* index_node, ElementsKind elements_kind,
     455             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
     456             : 
     457             :   // Context manipulation
     458             :   Node* LoadContextElement(Node* context, int slot_index);
     459             :   Node* LoadContextElement(Node* context, Node* slot_index);
     460             :   Node* StoreContextElement(Node* context, int slot_index, Node* value);
     461             :   Node* StoreContextElement(Node* context, Node* slot_index, Node* value);
     462             :   Node* StoreContextElementNoWriteBarrier(Node* context, int slot_index,
     463             :                                           Node* value);
     464             :   Node* LoadNativeContext(Node* context);
     465             : 
     466             :   Node* LoadJSArrayElementsMap(ElementsKind kind, Node* native_context);
     467             : 
     468             :   // Store the floating point value of a HeapNumber.
     469             :   Node* StoreHeapNumberValue(Node* object, Node* value);
     470             :   // Store a field to an object on the heap.
     471             :   Node* StoreObjectField(Node* object, int offset, Node* value);
     472             :   Node* StoreObjectField(Node* object, Node* offset, Node* value);
     473             :   Node* StoreObjectFieldNoWriteBarrier(
     474             :       Node* object, int offset, Node* value,
     475             :       MachineRepresentation rep = MachineRepresentation::kTagged);
     476             :   Node* StoreObjectFieldNoWriteBarrier(
     477             :       Node* object, Node* offset, Node* value,
     478             :       MachineRepresentation rep = MachineRepresentation::kTagged);
     479             :   // Store the Map of an HeapObject.
     480             :   Node* StoreMap(Node* object, Node* map);
     481             :   Node* StoreMapNoWriteBarrier(Node* object,
     482             :                                Heap::RootListIndex map_root_index);
     483             :   Node* StoreMapNoWriteBarrier(Node* object, Node* map);
     484             :   Node* StoreObjectFieldRoot(Node* object, int offset,
     485             :                              Heap::RootListIndex root);
     486             :   // Store an array element to a FixedArray.
     487        8463 :   Node* StoreFixedArrayElement(
     488             :       Node* object, int index, Node* value,
     489             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
     490             :     return StoreFixedArrayElement(object, IntPtrConstant(index), value,
     491        8463 :                                   barrier_mode);
     492             :   }
     493             : 
     494             :   Node* StoreFixedArrayElement(
     495             :       Node* object, Node* index, Node* value,
     496             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
     497             :       int additional_offset = 0,
     498             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
     499             : 
     500             :   Node* StoreFixedDoubleArrayElement(
     501             :       Node* object, Node* index, Node* value,
     502             :       ParameterMode parameter_mode = INTPTR_PARAMETERS);
     503             : 
     504             :   // EnsureArrayPushable verifies that receiver is:
     505             :   //   1. Is not a prototype.
     506             :   //   2. Is not a dictionary.
     507             :   //   3. Has a writeable length property.
     508             :   // It returns ElementsKind as a node for further division into cases.
     509             :   Node* EnsureArrayPushable(Node* receiver, Label* bailout);
     510             : 
     511             :   void TryStoreArrayElement(ElementsKind kind, ParameterMode mode,
     512             :                             Label* bailout, Node* elements, Node* index,
     513             :                             Node* value);
     514             :   // Consumes args into the array, and returns tagged new length.
     515             :   Node* BuildAppendJSArray(ElementsKind kind, Node* array,
     516             :                            CodeStubArguments& args, Variable& arg_index,
     517             :                            Label* bailout);
     518             :   // Pushes value onto the end of array.
     519             :   void BuildAppendJSArray(ElementsKind kind, Node* array, Node* value,
     520             :                           Label* bailout);
     521             : 
     522             :   void StoreFieldsNoWriteBarrier(Node* start_address, Node* end_address,
     523             :                                  Node* value);
     524             : 
     525             :   // Allocate a HeapNumber without initializing its value.
     526             :   Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE);
     527             :   // Allocate a HeapNumber with a specific value.
     528             :   Node* AllocateHeapNumberWithValue(Node* value, MutableMode mode = IMMUTABLE);
     529             :   // Allocate a SeqOneByteString with the given length.
     530             :   Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone);
     531             :   Node* AllocateSeqOneByteString(Node* context, Node* length,
     532             :                                  ParameterMode mode = INTPTR_PARAMETERS,
     533             :                                  AllocationFlags flags = kNone);
     534             :   // Allocate a SeqTwoByteString with the given length.
     535             :   Node* AllocateSeqTwoByteString(int length, AllocationFlags flags = kNone);
     536             :   Node* AllocateSeqTwoByteString(Node* context, Node* length,
     537             :                                  ParameterMode mode = INTPTR_PARAMETERS,
     538             :                                  AllocationFlags flags = kNone);
     539             : 
     540             :   // Allocate a SlicedOneByteString with the given length, parent and offset.
     541             :   // |length| and |offset| are expected to be tagged.
     542             :   Node* AllocateSlicedOneByteString(Node* length, Node* parent, Node* offset);
     543             :   // Allocate a SlicedTwoByteString with the given length, parent and offset.
     544             :   // |length| and |offset| are expected to be tagged.
     545             :   Node* AllocateSlicedTwoByteString(Node* length, Node* parent, Node* offset);
     546             : 
     547             :   // Allocate a one-byte ConsString with the given length, first and second
     548             :   // parts. |length| is expected to be tagged, and |first| and |second| are
     549             :   // expected to be one-byte strings.
     550             :   Node* AllocateOneByteConsString(Node* length, Node* first, Node* second,
     551             :                                   AllocationFlags flags = kNone);
     552             :   // Allocate a two-byte ConsString with the given length, first and second
     553             :   // parts. |length| is expected to be tagged, and |first| and |second| are
     554             :   // expected to be two-byte strings.
     555             :   Node* AllocateTwoByteConsString(Node* length, Node* first, Node* second,
     556             :                                   AllocationFlags flags = kNone);
     557             : 
     558             :   // Allocate an appropriate one- or two-byte ConsString with the first and
     559             :   // second parts specified by |first| and |second|.
     560             :   Node* NewConsString(Node* context, Node* length, Node* left, Node* right,
     561             :                       AllocationFlags flags = kNone);
     562             : 
     563             :   // Allocate a RegExpResult with the given length (the number of captures,
     564             :   // including the match itself), index (the index where the match starts),
     565             :   // and input string. |length| and |index| are expected to be tagged, and
     566             :   // |input| must be a string.
     567             :   Node* AllocateRegExpResult(Node* context, Node* length, Node* index,
     568             :                              Node* input);
     569             : 
     570             :   Node* AllocateNameDictionary(int capacity);
     571             :   Node* AllocateNameDictionary(Node* capacity);
     572             : 
     573             :   Node* AllocateJSObjectFromMap(Node* map, Node* properties = nullptr,
     574             :                                 Node* elements = nullptr,
     575             :                                 AllocationFlags flags = kNone);
     576             : 
     577             :   void InitializeJSObjectFromMap(Node* object, Node* map, Node* size,
     578             :                                  Node* properties = nullptr,
     579             :                                  Node* elements = nullptr);
     580             : 
     581             :   void InitializeJSObjectBody(Node* object, Node* map, Node* size,
     582             :                               int start_offset = JSObject::kHeaderSize);
     583             : 
     584             :   // Allocate a JSArray without elements and initialize the header fields.
     585             :   Node* AllocateUninitializedJSArrayWithoutElements(ElementsKind kind,
     586             :                                                     Node* array_map,
     587             :                                                     Node* length,
     588             :                                                     Node* allocation_site);
     589             :   // Allocate and return a JSArray with initialized header fields and its
     590             :   // uninitialized elements.
     591             :   // The ParameterMode argument is only used for the capacity parameter.
     592             :   std::pair<Node*, Node*> AllocateUninitializedJSArrayWithElements(
     593             :       ElementsKind kind, Node* array_map, Node* length, Node* allocation_site,
     594             :       Node* capacity, ParameterMode capacity_mode = INTPTR_PARAMETERS);
     595             :   // Allocate a JSArray and fill elements with the hole.
     596             :   // The ParameterMode argument is only used for the capacity parameter.
     597             :   Node* AllocateJSArray(ElementsKind kind, Node* array_map, Node* capacity,
     598             :                         Node* length, Node* allocation_site = nullptr,
     599             :                         ParameterMode capacity_mode = INTPTR_PARAMETERS);
     600             : 
     601             :   Node* AllocateFixedArray(ElementsKind kind, Node* capacity,
     602             :                            ParameterMode mode = INTPTR_PARAMETERS,
     603             :                            AllocationFlags flags = kNone);
     604             : 
     605             :   // Perform CreateArrayIterator (ES6 #sec-createarrayiterator).
     606             :   Node* CreateArrayIterator(Node* array, Node* array_map, Node* array_type,
     607             :                             Node* context, IterationKind mode);
     608             : 
     609             :   Node* AllocateJSArrayIterator(Node* array, Node* array_map, Node* map);
     610             : 
     611             :   // Perform ArraySpeciesCreate (ES6 #sec-arrayspeciescreate).
     612             :   Node* ArraySpeciesCreate(Node* context, Node* originalArray, Node* len);
     613             : 
     614             :   void FillFixedArrayWithValue(ElementsKind kind, Node* array, Node* from_index,
     615             :                                Node* to_index,
     616             :                                Heap::RootListIndex value_root_index,
     617             :                                ParameterMode mode = INTPTR_PARAMETERS);
     618             : 
     619             :   // Copies all elements from |from_array| of |length| size to
     620             :   // |to_array| of the same size respecting the elements kind.
     621             :   void CopyFixedArrayElements(
     622             :       ElementsKind kind, Node* from_array, Node* to_array, Node* length,
     623             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
     624             :       ParameterMode mode = INTPTR_PARAMETERS) {
     625             :     CopyFixedArrayElements(kind, from_array, kind, to_array, length, length,
     626        2838 :                            barrier_mode, mode);
     627             :   }
     628             : 
     629             :   // Copies |element_count| elements from |from_array| to |to_array| of
     630             :   // |capacity| size respecting both array's elements kinds.
     631             :   void CopyFixedArrayElements(
     632             :       ElementsKind from_kind, Node* from_array, ElementsKind to_kind,
     633             :       Node* to_array, Node* element_count, Node* capacity,
     634             :       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
     635             :       ParameterMode mode = INTPTR_PARAMETERS);
     636             : 
     637             :   // Copies |character_count| elements from |from_string| to |to_string|
     638             :   // starting at the |from_index|'th character. |from_string| and |to_string|
     639             :   // can either be one-byte strings or two-byte strings, although if
     640             :   // |from_string| is two-byte, then |to_string| must be two-byte.
     641             :   // |from_index|, |to_index| and |character_count| must be either Smis or
     642             :   // intptr_ts depending on |mode| s.t. 0 <= |from_index| <= |from_index| +
     643             :   // |character_count| <= from_string.length and 0 <= |to_index| <= |to_index| +
     644             :   // |character_count| <= to_string.length.
     645             :   void CopyStringCharacters(Node* from_string, Node* to_string,
     646             :                             Node* from_index, Node* to_index,
     647             :                             Node* character_count,
     648             :                             String::Encoding from_encoding,
     649             :                             String::Encoding to_encoding, ParameterMode mode);
     650             : 
     651             :   // Loads an element from |array| of |from_kind| elements by given |offset|
     652             :   // (NOTE: not index!), does a hole check if |if_hole| is provided and
     653             :   // converts the value so that it becomes ready for storing to array of
     654             :   // |to_kind| elements.
     655             :   Node* LoadElementAndPrepareForStore(Node* array, Node* offset,
     656             :                                       ElementsKind from_kind,
     657             :                                       ElementsKind to_kind, Label* if_hole);
     658             : 
     659             :   Node* CalculateNewElementsCapacity(Node* old_capacity,
     660             :                                      ParameterMode mode = INTPTR_PARAMETERS);
     661             : 
     662             :   // Tries to grow the |elements| array of given |object| to store the |key|
     663             :   // or bails out if the growing gap is too big. Returns new elements.
     664             :   Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind,
     665             :                                 Node* key, Label* bailout);
     666             : 
     667             :   // Tries to grow the |capacity|-length |elements| array of given |object|
     668             :   // to store the |key| or bails out if the growing gap is too big. Returns
     669             :   // new elements.
     670             :   Node* TryGrowElementsCapacity(Node* object, Node* elements, ElementsKind kind,
     671             :                                 Node* key, Node* capacity, ParameterMode mode,
     672             :                                 Label* bailout);
     673             : 
     674             :   // Grows elements capacity of given object. Returns new elements.
     675             :   Node* GrowElementsCapacity(Node* object, Node* elements,
     676             :                              ElementsKind from_kind, ElementsKind to_kind,
     677             :                              Node* capacity, Node* new_capacity,
     678             :                              ParameterMode mode, Label* bailout);
     679             : 
     680             :   // Given a need to grow by |growth|, allocate an appropriate new capacity
     681             :   // if necessary, and return a new elements FixedArray object. Label |bailout|
     682             :   // is followed for allocation failure.
     683             :   void PossiblyGrowElementsCapacity(ParameterMode mode, ElementsKind kind,
     684             :                                     Node* array, Node* length,
     685             :                                     Variable* var_elements, Node* growth,
     686             :                                     Label* bailout);
     687             : 
     688             :   // Allocation site manipulation
     689             :   void InitializeAllocationMemento(Node* base_allocation,
     690             :                                    int base_allocation_size,
     691             :                                    Node* allocation_site);
     692             : 
     693             :   Node* TryTaggedToFloat64(Node* value, Label* if_valueisnotnumber);
     694             :   Node* TruncateTaggedToFloat64(Node* context, Node* value);
     695             :   Node* TruncateTaggedToWord32(Node* context, Node* value);
     696             :   // Truncate the floating point value of a HeapNumber to an Int32.
     697             :   Node* TruncateHeapNumberValueToWord32(Node* object);
     698             : 
     699             :   // Conversions.
     700             :   Node* ChangeFloat64ToTagged(Node* value);
     701             :   Node* ChangeInt32ToTagged(Node* value);
     702             :   Node* ChangeUint32ToTagged(Node* value);
     703             :   Node* ChangeNumberToFloat64(Node* value);
     704             :   Node* ChangeNumberToIntPtr(Node* value);
     705             : 
     706             :   // Type conversions.
     707             :   // Throws a TypeError for {method_name} if {value} is not coercible to Object,
     708             :   // or returns the {value} converted to a String otherwise.
     709             :   Node* ToThisString(Node* context, Node* value, char const* method_name);
     710             :   // Throws a TypeError for {method_name} if {value} is neither of the given
     711             :   // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or
     712             :   // returns the {value} (or wrapped value) otherwise.
     713             :   Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type,
     714             :                     char const* method_name);
     715             : 
     716             :   // Throws a TypeError for {method_name} if {value} is not of the given
     717             :   // instance type. Returns {value}'s map.
     718             :   Node* ThrowIfNotInstanceType(Node* context, Node* value,
     719             :                                InstanceType instance_type,
     720             :                                char const* method_name);
     721             : 
     722             :   // Type checks.
     723             :   // Check whether the map is for an object with special properties, such as a
     724             :   // JSProxy or an object with interceptors.
     725             :   Node* InstanceTypeEqual(Node* instance_type, int type);
     726             :   Node* IsSpecialReceiverMap(Node* map);
     727             :   Node* IsSpecialReceiverInstanceType(Node* instance_type);
     728             :   Node* IsStringInstanceType(Node* instance_type);
     729             :   Node* IsOneByteStringInstanceType(Node* instance_type);
     730             :   Node* IsExternalStringInstanceType(Node* instance_type);
     731             :   Node* IsShortExternalStringInstanceType(Node* instance_type);
     732             :   Node* IsSequentialStringInstanceType(Node* instance_type);
     733             :   Node* IsConsStringInstanceType(Node* instance_type);
     734             :   Node* IsString(Node* object);
     735             :   Node* IsJSObject(Node* object);
     736             :   Node* IsJSGlobalProxy(Node* object);
     737             :   Node* IsJSReceiverInstanceType(Node* instance_type);
     738             :   Node* IsJSReceiver(Node* object);
     739             :   Node* IsJSReceiverMap(Node* map);
     740             :   Node* IsMap(Node* object);
     741             :   Node* IsCallableMap(Node* map);
     742             :   Node* IsDeprecatedMap(Node* map);
     743             :   Node* IsCallable(Node* object);
     744             :   Node* IsBoolean(Node* object);
     745             :   Node* IsPropertyCell(Node* object);
     746             :   Node* IsAccessorPair(Node* object);
     747             :   Node* IsHeapNumber(Node* object);
     748             :   Node* IsName(Node* object);
     749             :   Node* IsSymbol(Node* object);
     750             :   Node* IsPrivateSymbol(Node* object);
     751             :   Node* IsJSValue(Node* object);
     752             :   Node* IsJSArray(Node* object);
     753             :   Node* IsNativeContext(Node* object);
     754             :   Node* IsWeakCell(Node* object);
     755             :   Node* IsFixedDoubleArray(Node* object);
     756             :   Node* IsHashTable(Node* object);
     757             :   Node* IsDictionary(Node* object);
     758             :   Node* IsUnseededNumberDictionary(Node* object);
     759             :   Node* IsConstructorMap(Node* map);
     760             :   Node* IsJSFunction(Node* object);
     761             :   Node* IsJSTypedArray(Node* object);
     762             :   Node* IsJSArrayBuffer(Node* object);
     763             :   Node* IsFixedTypedArray(Node* object);
     764             :   Node* IsJSRegExp(Node* object);
     765             : 
     766             :   // True iff |object| is a Smi or a HeapNumber.
     767             :   Node* IsNumber(Node* object);
     768             : 
     769             :   // True iff |number| is either a Smi, or a HeapNumber whose value is not
     770             :   // within Smi range.
     771             :   Node* IsNumberNormalized(Node* number);
     772             : 
     773             :   // ElementsKind helpers:
     774             :   Node* IsFastElementsKind(Node* elements_kind);
     775             :   Node* IsHoleyFastElementsKind(Node* elements_kind);
     776             :   Node* IsElementsKindGreaterThan(Node* target_kind,
     777             :                                   ElementsKind reference_kind);
     778             : 
     779             :   // String helpers.
     780             :   // Load a character from a String (might flatten a ConsString).
     781             :   Node* StringCharCodeAt(Node* string, Node* index,
     782             :                          ParameterMode parameter_mode = SMI_PARAMETERS);
     783             :   // Return the single character string with only {code}.
     784             :   Node* StringFromCharCode(Node* code);
     785             :   // Return a new string object which holds a substring containing the range
     786             :   // [from,to[ of string.  |from| and |to| are expected to be tagged.
     787             :   Node* SubString(Node* context, Node* string, Node* from, Node* to);
     788             : 
     789             :   // Return a new string object produced by concatenating |first| with |second|.
     790             :   Node* StringAdd(Node* context, Node* first, Node* second,
     791             :                   AllocationFlags flags = kNone);
     792             : 
     793             :   // Unpack the external string, returning a pointer that (offset-wise) looks
     794             :   // like a sequential string.
     795             :   // Note that this pointer is not tagged and does not point to a real
     796             :   // sequential string instance, and may only be used to access the string
     797             :   // data. The pointer is GC-safe as long as a reference to the container
     798             :   // ExternalString is live.
     799             :   // |string| must be an external string. Bailout for short external strings.
     800             :   Node* TryDerefExternalString(Node* const string, Node* const instance_type,
     801             :                                Label* if_bailout);
     802             : 
     803             :   // Check if |var_string| has an indirect (thin or flat cons) string type,
     804             :   // and unpack it if so.
     805             :   void MaybeDerefIndirectString(Variable* var_string, Node* instance_type,
     806             :                                 Variable* var_did_something);
     807             :   // Check if |var_left| or |var_right| has an indirect (thin or flat cons)
     808             :   // string type, and unpack it/them if so. Fall through if nothing was done.
     809             :   void MaybeDerefIndirectStrings(Variable* var_left, Node* left_instance_type,
     810             :                                  Variable* var_right, Node* right_instance_type,
     811             :                                  Label* did_something);
     812             : 
     813             :   Node* StringFromCodePoint(Node* codepoint, UnicodeEncoding encoding);
     814             : 
     815             :   // Type conversion helpers.
     816             :   // Convert a String to a Number.
     817             :   Node* StringToNumber(Node* context, Node* input);
     818             :   Node* NumberToString(Node* context, Node* input);
     819             :   // Convert an object to a name.
     820             :   Node* ToName(Node* context, Node* input);
     821             :   // Convert a Non-Number object to a Number.
     822             :   Node* NonNumberToNumber(Node* context, Node* input);
     823             :   // Convert any object to a Number.
     824             :   Node* ToNumber(Node* context, Node* input);
     825             : 
     826             :   // Converts |input| to one of 2^32 integer values in the range 0 through
     827             :   // 2^32-1, inclusive.
     828             :   // ES#sec-touint32
     829             :   compiler::Node* ToUint32(compiler::Node* context, compiler::Node* input);
     830             : 
     831             :   // Convert any object to a String.
     832             :   Node* ToString(Node* context, Node* input);
     833             : 
     834             :   // Convert any object to a Primitive.
     835             :   Node* JSReceiverToPrimitive(Node* context, Node* input);
     836             : 
     837             :   enum ToIntegerTruncationMode {
     838             :     kNoTruncation,
     839             :     kTruncateMinusZero,
     840             :   };
     841             : 
     842             :   // ES6 7.1.17 ToIndex, but jumps to range_error if the result is not a Smi.
     843             :   Node* ToSmiIndex(Node* const input, Node* const context, Label* range_error);
     844             : 
     845             :   // ES6 7.1.15 ToLength, but jumps to range_error if the result is not a Smi.
     846             :   Node* ToSmiLength(Node* input, Node* const context, Label* range_error);
     847             : 
     848             :   // Convert any object to an Integer.
     849             :   Node* ToInteger(Node* context, Node* input,
     850             :                   ToIntegerTruncationMode mode = kNoTruncation);
     851             : 
     852             :   // Returns a node that contains a decoded (unsigned!) value of a bit
     853             :   // field |T| in |word32|. Returns result as an uint32 node.
     854             :   template <typename T>
     855             :   Node* DecodeWord32(Node* word32) {
     856       14432 :     return DecodeWord32(word32, T::kShift, T::kMask);
     857             :   }
     858             : 
     859             :   // Returns a node that contains a decoded (unsigned!) value of a bit
     860             :   // field |T| in |word|. Returns result as a word-size node.
     861             :   template <typename T>
     862             :   Node* DecodeWord(Node* word) {
     863       16275 :     return DecodeWord(word, T::kShift, T::kMask);
     864             :   }
     865             : 
     866             :   // Returns a node that contains a decoded (unsigned!) value of a bit
     867             :   // field |T| in |word32|. Returns result as a word-size node.
     868             :   template <typename T>
     869        3117 :   Node* DecodeWordFromWord32(Node* word32) {
     870        6234 :     return DecodeWord<T>(ChangeUint32ToWord(word32));
     871             :   }
     872             : 
     873             :   // Returns a node that contains a decoded (unsigned!) value of a bit
     874             :   // field |T| in |word|. Returns result as an uint32 node.
     875             :   template <typename T>
     876          43 :   Node* DecodeWord32FromWord(Node* word) {
     877          43 :     return TruncateWordToWord32(DecodeWord<T>(word));
     878             :   }
     879             : 
     880             :   // Decodes an unsigned (!) value from |word32| to an uint32 node.
     881             :   Node* DecodeWord32(Node* word32, uint32_t shift, uint32_t mask);
     882             : 
     883             :   // Decodes an unsigned (!) value from |word| to a word-size node.
     884             :   Node* DecodeWord(Node* word, uint32_t shift, uint32_t mask);
     885             : 
     886             :   // Returns true if any of the |T|'s bits in given |word32| are set.
     887             :   template <typename T>
     888             :   Node* IsSetWord32(Node* word32) {
     889        8691 :     return IsSetWord32(word32, T::kMask);
     890             :   }
     891             : 
     892             :   // Returns true if any of the mask's bits in given |word32| are set.
     893       11106 :   Node* IsSetWord32(Node* word32, uint32_t mask) {
     894             :     return Word32NotEqual(Word32And(word32, Int32Constant(mask)),
     895       11106 :                           Int32Constant(0));
     896             :   }
     897             : 
     898             :   // Returns true if any of the |T|'s bits in given |word| are set.
     899             :   template <typename T>
     900             :   Node* IsSetWord(Node* word) {
     901       10664 :     return IsSetWord(word, T::kMask);
     902             :   }
     903             : 
     904             :   // Returns true if any of the mask's bits in given |word| are set.
     905       13810 :   Node* IsSetWord(Node* word, uint32_t mask) {
     906       13810 :     return WordNotEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
     907             :   }
     908             : 
     909             :   // Returns true if any of the mask's bit are set in the given Smi.
     910             :   // Smi-encoding of the mask is performed implicitly!
     911         473 :   Node* IsSetSmi(Node* smi, int untagged_mask) {
     912             :     intptr_t mask_word = bit_cast<intptr_t>(Smi::FromInt(untagged_mask));
     913             :     return WordNotEqual(
     914             :         WordAnd(BitcastTaggedToWord(smi), IntPtrConstant(mask_word)),
     915         473 :         IntPtrConstant(0));
     916             :   }
     917             : 
     918             :   // Returns true if all of the |T|'s bits in given |word32| are clear.
     919             :   template <typename T>
     920             :   Node* IsClearWord32(Node* word32) {
     921         129 :     return IsClearWord32(word32, T::kMask);
     922             :   }
     923             : 
     924             :   // Returns true if all of the mask's bits in given |word32| are clear.
     925         129 :   Node* IsClearWord32(Node* word32, uint32_t mask) {
     926             :     return Word32Equal(Word32And(word32, Int32Constant(mask)),
     927         129 :                        Int32Constant(0));
     928             :   }
     929             : 
     930             :   // Returns true if all of the |T|'s bits in given |word| are clear.
     931             :   template <typename T>
     932             :   Node* IsClearWord(Node* word) {
     933             :     return IsClearWord(word, T::kMask);
     934             :   }
     935             : 
     936             :   // Returns true if all of the mask's bits in given |word| are clear.
     937             :   Node* IsClearWord(Node* word, uint32_t mask) {
     938             :     return WordEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
     939             :   }
     940             : 
     941             :   void SetCounter(StatsCounter* counter, int value);
     942             :   void IncrementCounter(StatsCounter* counter, int delta);
     943             :   void DecrementCounter(StatsCounter* counter, int delta);
     944             : 
     945             :   void Increment(Variable& variable, int value = 1,
     946             :                  ParameterMode mode = INTPTR_PARAMETERS);
     947             : 
     948             :   // Generates "if (false) goto label" code. Useful for marking a label as
     949             :   // "live" to avoid assertion failures during graph building. In the resulting
     950             :   // code this check will be eliminated.
     951             :   void Use(Label* label);
     952             : 
     953             :   // Various building blocks for stubs doing property lookups.
     954             : 
     955             :   // |if_notinternalized| is optional; |if_bailout| will be used by default.
     956             :   void TryToName(Node* key, Label* if_keyisindex, Variable* var_index,
     957             :                  Label* if_keyisunique, Variable* var_unique, Label* if_bailout,
     958             :                  Label* if_notinternalized = nullptr);
     959             : 
     960             :   // Performs a hash computation and string table lookup for the given string,
     961             :   // and jumps to:
     962             :   // - |if_index| if the string is an array index like "123"; |var_index|
     963             :   //              will contain the intptr representation of that index.
     964             :   // - |if_internalized| if the string exists in the string table; the
     965             :   //                     internalized version will be in |var_internalized|.
     966             :   // - |if_not_internalized| if the string is not in the string table (but
     967             :   //                         does not add it).
     968             :   // - |if_bailout| for unsupported cases (e.g. uncachable array index).
     969             :   void TryInternalizeString(Node* string, Label* if_index, Variable* var_index,
     970             :                             Label* if_internalized, Variable* var_internalized,
     971             :                             Label* if_not_internalized, Label* if_bailout);
     972             : 
     973             :   // Calculates array index for given dictionary entry and entry field.
     974             :   // See Dictionary::EntryToIndex().
     975             :   template <typename Dictionary>
     976             :   Node* EntryToIndex(Node* entry, int field_index);
     977             :   template <typename Dictionary>
     978             :   Node* EntryToIndex(Node* entry) {
     979       29091 :     return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
     980             :   }
     981             : 
     982             :   // Loads the details for the entry with the given key_index.
     983             :   // Returns an untagged int32.
     984             :   template <class ContainerType>
     985             :   Node* LoadDetailsByKeyIndex(Node* container, Node* key_index) {
     986             :     const int kKeyToDetailsOffset =
     987             :         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
     988             :         kPointerSize;
     989             :     return LoadAndUntagToWord32FixedArrayElement(container, key_index,
     990        4658 :                                                  kKeyToDetailsOffset);
     991             :   }
     992             : 
     993             :   // Loads the value for the entry with the given key_index.
     994             :   // Returns a tagged value.
     995             :   template <class ContainerType>
     996             :   Node* LoadValueByKeyIndex(Node* container, Node* key_index) {
     997             :     const int kKeyToValueOffset =
     998             :         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
     999             :         kPointerSize;
    1000        4801 :     return LoadFixedArrayElement(container, key_index, kKeyToValueOffset);
    1001             :   }
    1002             : 
    1003             :   // Stores the details for the entry with the given key_index.
    1004             :   // |details| must be a Smi.
    1005             :   template <class ContainerType>
    1006             :   void StoreDetailsByKeyIndex(Node* container, Node* key_index, Node* details) {
    1007             :     const int kKeyToDetailsOffset =
    1008             :         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
    1009             :         kPointerSize;
    1010         473 :     StoreFixedArrayElement(container, key_index, details, SKIP_WRITE_BARRIER,
    1011             :                            kKeyToDetailsOffset);
    1012             :   }
    1013             : 
    1014             :   // Stores the value for the entry with the given key_index.
    1015             :   template <class ContainerType>
    1016             :   void StoreValueByKeyIndex(
    1017             :       Node* container, Node* key_index, Node* value,
    1018             :       WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER) {
    1019             :     const int kKeyToValueOffset =
    1020             :         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
    1021             :         kPointerSize;
    1022        1161 :     StoreFixedArrayElement(container, key_index, value, write_barrier,
    1023             :                            kKeyToValueOffset);
    1024             :   }
    1025             : 
    1026             :   // Calculate a valid size for the a hash table.
    1027             :   Node* HashTableComputeCapacity(Node* at_least_space_for);
    1028             : 
    1029             :   template <class Dictionary>
    1030             :   Node* GetNumberOfElements(Node* dictionary) {
    1031             :     return LoadFixedArrayElement(dictionary,
    1032         473 :                                  Dictionary::kNumberOfElementsIndex);
    1033             :   }
    1034             : 
    1035             :   template <class Dictionary>
    1036             :   void SetNumberOfElements(Node* dictionary, Node* num_elements_smi) {
    1037         473 :     StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex,
    1038             :                            num_elements_smi, SKIP_WRITE_BARRIER);
    1039             :   }
    1040             : 
    1041             :   template <class Dictionary>
    1042             :   Node* GetNumberOfDeletedElements(Node* dictionary) {
    1043             :     return LoadFixedArrayElement(dictionary,
    1044         473 :                                  Dictionary::kNumberOfDeletedElementsIndex);
    1045             :   }
    1046             : 
    1047             :   template <class Dictionary>
    1048             :   void SetNumberOfDeletedElements(Node* dictionary, Node* num_deleted_smi) {
    1049          43 :     StoreFixedArrayElement(dictionary,
    1050             :                            Dictionary::kNumberOfDeletedElementsIndex,
    1051             :                            num_deleted_smi, SKIP_WRITE_BARRIER);
    1052             :   }
    1053             : 
    1054             :   template <class Dictionary>
    1055             :   Node* GetCapacity(Node* dictionary) {
    1056        7115 :     return LoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex);
    1057             :   }
    1058             : 
    1059             :   template <class Dictionary>
    1060             :   Node* GetNextEnumerationIndex(Node* dictionary);
    1061             : 
    1062             :   template <class Dictionary>
    1063             :   void SetNextEnumerationIndex(Node* dictionary, Node* next_enum_index_smi);
    1064             : 
    1065             :   // Looks up an entry in a NameDictionaryBase successor. If the entry is found
    1066             :   // control goes to {if_found} and {var_name_index} contains an index of the
    1067             :   // key field of the entry found. If the key is not found control goes to
    1068             :   // {if_not_found}.
    1069             :   static const int kInlinedDictionaryProbes = 4;
    1070             :   enum LookupMode { kFindExisting, kFindInsertionIndex };
    1071             :   template <typename Dictionary>
    1072             :   void NameDictionaryLookup(Node* dictionary, Node* unique_name,
    1073             :                             Label* if_found, Variable* var_name_index,
    1074             :                             Label* if_not_found,
    1075             :                             int inlined_probes = kInlinedDictionaryProbes,
    1076             :                             LookupMode mode = kFindExisting);
    1077             : 
    1078             :   Node* ComputeIntegerHash(Node* key, Node* seed);
    1079             : 
    1080             :   template <typename Dictionary>
    1081             :   void NumberDictionaryLookup(Node* dictionary, Node* intptr_index,
    1082             :                               Label* if_found, Variable* var_entry,
    1083             :                               Label* if_not_found);
    1084             : 
    1085             :   template <class Dictionary>
    1086             :   void FindInsertionEntry(Node* dictionary, Node* key, Variable* var_key_index);
    1087             : 
    1088             :   template <class Dictionary>
    1089             :   void InsertEntry(Node* dictionary, Node* key, Node* value, Node* index,
    1090             :                    Node* enum_index);
    1091             : 
    1092             :   template <class Dictionary>
    1093             :   void Add(Node* dictionary, Node* key, Node* value, Label* bailout);
    1094             : 
    1095             :   // Tries to check if {object} has own {unique_name} property.
    1096             :   void TryHasOwnProperty(Node* object, Node* map, Node* instance_type,
    1097             :                          Node* unique_name, Label* if_found,
    1098             :                          Label* if_not_found, Label* if_bailout);
    1099             : 
    1100             :   // Tries to get {object}'s own {unique_name} property value. If the property
    1101             :   // is an accessor then it also calls a getter. If the property is a double
    1102             :   // field it re-wraps value in an immutable heap number.
    1103             :   void TryGetOwnProperty(Node* context, Node* receiver, Node* object, Node* map,
    1104             :                          Node* instance_type, Node* unique_name,
    1105             :                          Label* if_found, Variable* var_value,
    1106             :                          Label* if_not_found, Label* if_bailout);
    1107             : 
    1108        2623 :   Node* GetProperty(Node* context, Node* receiver, Handle<Name> name) {
    1109        2623 :     return GetProperty(context, receiver, HeapConstant(name));
    1110             :   }
    1111             : 
    1112        3182 :   Node* GetProperty(Node* context, Node* receiver, Node* const name) {
    1113             :     return CallStub(CodeFactory::GetProperty(isolate()), context, receiver,
    1114        3182 :                     name);
    1115             :   }
    1116             : 
    1117             :   template <class... TArgs>
    1118        3311 :   Node* CallBuiltin(Builtins::Name id, Node* context, TArgs... args) {
    1119        3311 :     return CallStub(Builtins::CallableFor(isolate(), id), context, args...);
    1120             :   }
    1121             : 
    1122             :   template <class... TArgs>
    1123          43 :   Node* TailCallBuiltin(Builtins::Name id, Node* context, TArgs... args) {
    1124          43 :     return TailCallStub(Builtins::CallableFor(isolate(), id), context, args...);
    1125             :   }
    1126             : 
    1127             :   void LoadPropertyFromFastObject(Node* object, Node* map, Node* descriptors,
    1128             :                                   Node* name_index, Variable* var_details,
    1129             :                                   Variable* var_value);
    1130             : 
    1131             :   void LoadPropertyFromNameDictionary(Node* dictionary, Node* entry,
    1132             :                                       Variable* var_details,
    1133             :                                       Variable* var_value);
    1134             : 
    1135             :   void LoadPropertyFromGlobalDictionary(Node* dictionary, Node* entry,
    1136             :                                         Variable* var_details,
    1137             :                                         Variable* var_value, Label* if_deleted);
    1138             : 
    1139             :   // Generic property lookup generator. If the {object} is fast and
    1140             :   // {unique_name} property is found then the control goes to {if_found_fast}
    1141             :   // label and {var_meta_storage} and {var_name_index} will contain
    1142             :   // DescriptorArray and an index of the descriptor's name respectively.
    1143             :   // If the {object} is slow or global then the control goes to {if_found_dict}
    1144             :   // or {if_found_global} and the {var_meta_storage} and {var_name_index} will
    1145             :   // contain a dictionary and an index of the key field of the found entry.
    1146             :   // If property is not found or given lookup is not supported then
    1147             :   // the control goes to {if_not_found} or {if_bailout} respectively.
    1148             :   //
    1149             :   // Note: this code does not check if the global dictionary points to deleted
    1150             :   // entry! This has to be done by the caller.
    1151             :   void TryLookupProperty(Node* object, Node* map, Node* instance_type,
    1152             :                          Node* unique_name, Label* if_found_fast,
    1153             :                          Label* if_found_dict, Label* if_found_global,
    1154             :                          Variable* var_meta_storage, Variable* var_name_index,
    1155             :                          Label* if_not_found, Label* if_bailout);
    1156             : 
    1157             :   // This method jumps to if_found if the element is known to exist. To
    1158             :   // if_absent if it's known to not exist. To if_not_found if the prototype
    1159             :   // chain needs to be checked. And if_bailout if the lookup is unsupported.
    1160             :   void TryLookupElement(Node* object, Node* map, Node* instance_type,
    1161             :                         Node* intptr_index, Label* if_found, Label* if_absent,
    1162             :                         Label* if_not_found, Label* if_bailout);
    1163             : 
    1164             :   // This is a type of a lookup in holder generator function. In case of a
    1165             :   // property lookup the {key} is guaranteed to be an unique name and in case of
    1166             :   // element lookup the key is an Int32 index.
    1167             :   typedef std::function<void(Node* receiver, Node* holder, Node* map,
    1168             :                              Node* instance_type, Node* key, Label* next_holder,
    1169             :                              Label* if_bailout)>
    1170             :       LookupInHolder;
    1171             : 
    1172             :   // Generic property prototype chain lookup generator.
    1173             :   // For properties it generates lookup using given {lookup_property_in_holder}
    1174             :   // and for elements it uses {lookup_element_in_holder}.
    1175             :   // Upon reaching the end of prototype chain the control goes to {if_end}.
    1176             :   // If it can't handle the case {receiver}/{key} case then the control goes
    1177             :   // to {if_bailout}.
    1178             :   void TryPrototypeChainLookup(Node* receiver, Node* key,
    1179             :                                const LookupInHolder& lookup_property_in_holder,
    1180             :                                const LookupInHolder& lookup_element_in_holder,
    1181             :                                Label* if_end, Label* if_bailout);
    1182             : 
    1183             :   // Instanceof helpers.
    1184             :   // ES6 section 7.3.19 OrdinaryHasInstance (C, O)
    1185             :   Node* OrdinaryHasInstance(Node* context, Node* callable, Node* object);
    1186             : 
    1187             :   // Load type feedback vector from the stub caller's frame.
    1188             :   Node* LoadFeedbackVectorForStub();
    1189             : 
    1190             :   // Update the type feedback vector.
    1191             :   void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id);
    1192             : 
    1193             :   // Check if a property name might require protector invalidation when it is
    1194             :   // used for a property store or deletion.
    1195             :   void CheckForAssociatedProtector(Node* name, Label* if_protector);
    1196             : 
    1197             :   Node* LoadReceiverMap(Node* receiver);
    1198             : 
    1199             :   // Emits keyed sloppy arguments load. Returns either the loaded value.
    1200             :   Node* LoadKeyedSloppyArguments(Node* receiver, Node* key, Label* bailout) {
    1201         350 :     return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout);
    1202             :   }
    1203             : 
    1204             :   // Emits keyed sloppy arguments store.
    1205             :   void StoreKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
    1206             :                                  Label* bailout) {
    1207             :     DCHECK_NOT_NULL(value);
    1208           0 :     EmitKeyedSloppyArguments(receiver, key, value, bailout);
    1209             :   }
    1210             : 
    1211             :   // Loads script context from the script context table.
    1212             :   Node* LoadScriptContext(Node* context, int context_index);
    1213             : 
    1214             :   Node* Int32ToUint8Clamped(Node* int32_value);
    1215             :   Node* Float64ToUint8Clamped(Node* float64_value);
    1216             : 
    1217             :   Node* PrepareValueForWriteToTypedArray(Node* key, ElementsKind elements_kind,
    1218             :                                          Label* bailout);
    1219             : 
    1220             :   // Store value to an elements array with given elements kind.
    1221             :   void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
    1222             :                     ParameterMode mode);
    1223             : 
    1224             :   void EmitElementStore(Node* object, Node* key, Node* value, bool is_jsarray,
    1225             :                         ElementsKind elements_kind,
    1226             :                         KeyedAccessStoreMode store_mode, Label* bailout);
    1227             : 
    1228             :   Node* CheckForCapacityGrow(Node* object, Node* elements, ElementsKind kind,
    1229             :                              Node* length, Node* key, ParameterMode mode,
    1230             :                              bool is_js_array, Label* bailout);
    1231             : 
    1232             :   Node* CopyElementsOnWrite(Node* object, Node* elements, ElementsKind kind,
    1233             :                             Node* length, ParameterMode mode, Label* bailout);
    1234             : 
    1235             :   void TransitionElementsKind(Node* object, Node* map, ElementsKind from_kind,
    1236             :                               ElementsKind to_kind, bool is_jsarray,
    1237             :                               Label* bailout);
    1238             : 
    1239             :   void TrapAllocationMemento(Node* object, Label* memento_found);
    1240             : 
    1241             :   Node* PageFromAddress(Node* address);
    1242             : 
    1243             :   // Create a new weak cell with a specified value and install it into a
    1244             :   // feedback vector.
    1245             :   Node* CreateWeakCellInFeedbackVector(Node* feedback_vector, Node* slot,
    1246             :                                        Node* value);
    1247             : 
    1248             :   // Create a new AllocationSite and install it into a feedback vector.
    1249             :   Node* CreateAllocationSiteInFeedbackVector(Node* feedback_vector, Node* slot);
    1250             : 
    1251             :   enum class IndexAdvanceMode { kPre, kPost };
    1252             : 
    1253             :   typedef std::function<void(Node* index)> FastLoopBody;
    1254             : 
    1255             :   Node* BuildFastLoop(const VariableList& var_list, Node* start_index,
    1256             :                       Node* end_index, const FastLoopBody& body, int increment,
    1257             :                       ParameterMode parameter_mode,
    1258             :                       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre);
    1259             : 
    1260        5444 :   Node* BuildFastLoop(Node* start_index, Node* end_index,
    1261             :                       const FastLoopBody& body, int increment,
    1262             :                       ParameterMode parameter_mode,
    1263             :                       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre) {
    1264             :     return BuildFastLoop(VariableList(0, zone()), start_index, end_index, body,
    1265        5444 :                          increment, parameter_mode, advance_mode);
    1266             :   }
    1267             : 
    1268             :   enum class ForEachDirection { kForward, kReverse };
    1269             : 
    1270             :   typedef std::function<void(Node* fixed_array, Node* offset)>
    1271             :       FastFixedArrayForEachBody;
    1272             : 
    1273             :   void BuildFastFixedArrayForEach(
    1274             :       const CodeStubAssembler::VariableList& vars, Node* fixed_array,
    1275             :       ElementsKind kind, Node* first_element_inclusive,
    1276             :       Node* last_element_exclusive, const FastFixedArrayForEachBody& body,
    1277             :       ParameterMode mode = INTPTR_PARAMETERS,
    1278             :       ForEachDirection direction = ForEachDirection::kReverse);
    1279             : 
    1280        5971 :   void BuildFastFixedArrayForEach(
    1281             :       Node* fixed_array, ElementsKind kind, Node* first_element_inclusive,
    1282             :       Node* last_element_exclusive, const FastFixedArrayForEachBody& body,
    1283             :       ParameterMode mode = INTPTR_PARAMETERS,
    1284             :       ForEachDirection direction = ForEachDirection::kReverse) {
    1285        5971 :     CodeStubAssembler::VariableList list(0, zone());
    1286             :     BuildFastFixedArrayForEach(list, fixed_array, kind, first_element_inclusive,
    1287        5971 :                                last_element_exclusive, body, mode, direction);
    1288        5971 :   }
    1289             : 
    1290             :   Node* GetArrayAllocationSize(Node* element_count, ElementsKind kind,
    1291             :                                ParameterMode mode, int header_size) {
    1292       12069 :     return ElementOffsetFromIndex(element_count, kind, mode, header_size);
    1293             :   }
    1294             : 
    1295             :   Node* GetFixedArrayAllocationSize(Node* element_count, ElementsKind kind,
    1296             :                                     ParameterMode mode) {
    1297             :     return GetArrayAllocationSize(element_count, kind, mode,
    1298             :                                   FixedArray::kHeaderSize);
    1299             :   }
    1300             : 
    1301             :   void GotoIfFixedArraySizeDoesntFitInNewSpace(Node* element_count,
    1302             :                                                Label* doesnt_fit, int base_size,
    1303             :                                                ParameterMode mode);
    1304             : 
    1305             :   void InitializeFieldsWithRoot(Node* object, Node* start_offset,
    1306             :                                 Node* end_offset, Heap::RootListIndex root);
    1307             : 
    1308             :   enum RelationalComparisonMode {
    1309             :     kLessThan,
    1310             :     kLessThanOrEqual,
    1311             :     kGreaterThan,
    1312             :     kGreaterThanOrEqual
    1313             :   };
    1314             : 
    1315             :   Node* RelationalComparison(RelationalComparisonMode mode, Node* lhs,
    1316             :                              Node* rhs, Node* context);
    1317             : 
    1318             :   void BranchIfNumericRelationalComparison(RelationalComparisonMode mode,
    1319             :                                            Node* lhs, Node* rhs, Label* if_true,
    1320             :                                            Label* if_false);
    1321             : 
    1322             :   void GotoUnlessNumberLessThan(Node* lhs, Node* rhs, Label* if_false);
    1323             : 
    1324             :   Node* Equal(Node* lhs, Node* rhs, Node* context);
    1325             : 
    1326             :   Node* StrictEqual(Node* lhs, Node* rhs);
    1327             : 
    1328             :   // ECMA#sec-samevalue
    1329             :   // Similar to StrictEqual except that NaNs are treated as equal and minus zero
    1330             :   // differs from positive zero.
    1331             :   // Unlike Equal and StrictEqual, returns a value suitable for use in Branch
    1332             :   // instructions, e.g. Branch(SameValue(...), &label).
    1333             :   Node* SameValue(Node* lhs, Node* rhs);
    1334             : 
    1335             :   Node* HasProperty(
    1336             :       Node* object, Node* key, Node* context,
    1337             :       Runtime::FunctionId fallback_runtime_function_id = Runtime::kHasProperty);
    1338             : 
    1339             :   Node* ClassOf(Node* object);
    1340             : 
    1341             :   Node* Typeof(Node* value);
    1342             : 
    1343             :   Node* GetSuperConstructor(Node* value, Node* context);
    1344             : 
    1345             :   Node* InstanceOf(Node* object, Node* callable, Node* context);
    1346             : 
    1347             :   // Debug helpers
    1348             :   Node* IsDebugActive();
    1349             : 
    1350             :   // TypedArray/ArrayBuffer helpers
    1351             :   Node* IsDetachedBuffer(Node* buffer);
    1352             : 
    1353             :   Node* ElementOffsetFromIndex(Node* index, ElementsKind kind,
    1354             :                                ParameterMode mode, int base_size = 0);
    1355             : 
    1356             :   Node* AllocateFunctionWithMapAndContext(Node* map, Node* shared_info,
    1357             :                                           Node* context);
    1358             : 
    1359             :   // Promise helpers
    1360             :   Node* IsPromiseHookEnabledOrDebugIsActive();
    1361             : 
    1362             :   Node* AllocatePromiseReactionJobInfo(Node* value, Node* tasks,
    1363             :                                        Node* deferred_promise,
    1364             :                                        Node* deferred_on_resolve,
    1365             :                                        Node* deferred_on_reject, Node* context);
    1366             : 
    1367             :   // Helpers for StackFrame markers.
    1368             :   Node* MarkerIsFrameType(Node* marker_or_function,
    1369             :                           StackFrame::Type frame_type);
    1370             :   Node* MarkerIsNotFrameType(Node* marker_or_function,
    1371             :                              StackFrame::Type frame_type);
    1372             : 
    1373             :   // Support for printf-style debugging
    1374             :   void Print(const char* s);
    1375             :   void Print(const char* prefix, Node* tagged_value);
    1376             :   inline void Print(Node* tagged_value) { return Print(nullptr, tagged_value); }
    1377             : 
    1378             :   template <class... TArgs>
    1379         387 :   Node* MakeTypeError(MessageTemplate::Template message, Node* context,
    1380             :                       TArgs... args) {
    1381             :     STATIC_ASSERT(sizeof...(TArgs) <= 3);
    1382             :     Node* const make_type_error = LoadContextElement(
    1383         387 :         LoadNativeContext(context), Context::MAKE_TYPE_ERROR_INDEX);
    1384             :     return CallJS(CodeFactory::Call(isolate()), context, make_type_error,
    1385         387 :                   UndefinedConstant(), SmiConstant(message), args...);
    1386             :   }
    1387             : 
    1388             :  protected:
    1389             :   void DescriptorLookup(Node* unique_name, Node* descriptors, Node* bitfield3,
    1390             :                         Label* if_found, Variable* var_name_index,
    1391             :                         Label* if_not_found);
    1392             :   void DescriptorLookupLinear(Node* unique_name, Node* descriptors, Node* nof,
    1393             :                               Label* if_found, Variable* var_name_index,
    1394             :                               Label* if_not_found);
    1395             :   void DescriptorLookupBinary(Node* unique_name, Node* descriptors, Node* nof,
    1396             :                               Label* if_found, Variable* var_name_index,
    1397             :                               Label* if_not_found);
    1398             :   // Implements DescriptorArray::ToKeyIndex.
    1399             :   // Returns an untagged IntPtr.
    1400             :   Node* DescriptorArrayToKeyIndex(Node* descriptor_number);
    1401             : 
    1402             :   Node* CallGetterIfAccessor(Node* value, Node* details, Node* context,
    1403             :                              Node* receiver, Label* if_bailout);
    1404             : 
    1405             :   Node* TryToIntptr(Node* key, Label* miss);
    1406             : 
    1407             :   void BranchIfPrototypesHaveNoElements(Node* receiver_map,
    1408             :                                         Label* definitely_no_elements,
    1409             :                                         Label* possibly_elements);
    1410             : 
    1411             :  private:
    1412             :   friend class CodeStubArguments;
    1413             : 
    1414             :   void HandleBreakOnNode();
    1415             : 
    1416             :   Node* AllocateRawDoubleAligned(Node* size_in_bytes, AllocationFlags flags,
    1417             :                                  Node* top_address, Node* limit_address);
    1418             :   Node* AllocateRawUnaligned(Node* size_in_bytes, AllocationFlags flags,
    1419             :                              Node* top_adddress, Node* limit_address);
    1420             :   Node* AllocateRaw(Node* size_in_bytes, AllocationFlags flags,
    1421             :                     Node* top_address, Node* limit_address);
    1422             :   // Allocate and return a JSArray of given total size in bytes with header
    1423             :   // fields initialized.
    1424             :   Node* AllocateUninitializedJSArray(ElementsKind kind, Node* array_map,
    1425             :                                      Node* length, Node* allocation_site,
    1426             :                                      Node* size_in_bytes);
    1427             : 
    1428             :   Node* SmiShiftBitsConstant();
    1429             : 
    1430             :   // Emits keyed sloppy arguments load if the |value| is nullptr or store
    1431             :   // otherwise. Returns either the loaded value or |value|.
    1432             :   Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
    1433             :                                  Label* bailout);
    1434             : 
    1435             :   Node* AllocateSlicedString(Heap::RootListIndex map_root_index, Node* length,
    1436             :                              Node* parent, Node* offset);
    1437             : 
    1438             :   Node* AllocateConsString(Heap::RootListIndex map_root_index, Node* length,
    1439             :                            Node* first, Node* second, AllocationFlags flags);
    1440             : 
    1441             :   // Implements DescriptorArray::number_of_entries.
    1442             :   // Returns an untagged int32.
    1443             :   Node* DescriptorArrayNumberOfEntries(Node* descriptors);
    1444             :   // Implements DescriptorArray::GetSortedKeyIndex.
    1445             :   // Returns an untagged int32.
    1446             :   Node* DescriptorArrayGetSortedKeyIndex(Node* descriptors,
    1447             :                                          Node* descriptor_number);
    1448             :   // Implements DescriptorArray::GetKey.
    1449             :   Node* DescriptorArrayGetKey(Node* descriptors, Node* descriptor_number);
    1450             : 
    1451             :   static const int kElementLoopUnrollThreshold = 8;
    1452             : };
    1453             : 
    1454             : class CodeStubArguments {
    1455             :  public:
    1456             :   typedef compiler::Node Node;
    1457             : 
    1458             :   // |argc| is an uint32 value which specifies the number of arguments passed
    1459             :   // to the builtin excluding the receiver.
    1460             :   CodeStubArguments(CodeStubAssembler* assembler, Node* argc)
    1461             :       : CodeStubArguments(assembler, argc, nullptr,
    1462         344 :                           CodeStubAssembler::INTPTR_PARAMETERS) {}
    1463             :   CodeStubArguments(CodeStubAssembler* assembler, Node* argc, Node* fp,
    1464             :                     CodeStubAssembler::ParameterMode param_mode);
    1465             : 
    1466             :   Node* GetReceiver() const;
    1467             : 
    1468             :   Node* AtIndexPtr(Node* index, CodeStubAssembler::ParameterMode mode =
    1469             :                                     CodeStubAssembler::INTPTR_PARAMETERS) const;
    1470             : 
    1471             :   // |index| is zero-based and does not include the receiver
    1472             :   Node* AtIndex(Node* index, CodeStubAssembler::ParameterMode mode =
    1473             :                                  CodeStubAssembler::INTPTR_PARAMETERS) const;
    1474             : 
    1475             :   Node* AtIndex(int index) const;
    1476             : 
    1477             :   Node* GetLength() const { return argc_; }
    1478             : 
    1479             :   typedef std::function<void(Node* arg)> ForEachBodyFunction;
    1480             : 
    1481             :   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
    1482          43 :   void ForEach(const ForEachBodyFunction& body, Node* first = nullptr,
    1483             :                Node* last = nullptr, CodeStubAssembler::ParameterMode mode =
    1484             :                                          CodeStubAssembler::INTPTR_PARAMETERS) {
    1485          43 :     CodeStubAssembler::VariableList list(0, assembler_->zone());
    1486          43 :     ForEach(list, body, first, last);
    1487          43 :   }
    1488             : 
    1489             :   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
    1490             :   void ForEach(const CodeStubAssembler::VariableList& vars,
    1491             :                const ForEachBodyFunction& body, Node* first = nullptr,
    1492             :                Node* last = nullptr, CodeStubAssembler::ParameterMode mode =
    1493             :                                          CodeStubAssembler::INTPTR_PARAMETERS);
    1494             : 
    1495             :   void PopAndReturn(Node* value);
    1496             : 
    1497             :  private:
    1498             :   Node* GetArguments();
    1499             : 
    1500             :   CodeStubAssembler* assembler_;
    1501             :   CodeStubAssembler::ParameterMode argc_mode_;
    1502             :   Node* argc_;
    1503             :   Node* arguments_;
    1504             :   Node* fp_;
    1505             : };
    1506             : 
    1507        5590 : class ToDirectStringAssembler : public CodeStubAssembler {
    1508             :  private:
    1509             :   enum StringPointerKind { PTR_TO_DATA, PTR_TO_STRING };
    1510             : 
    1511             :  public:
    1512             :   explicit ToDirectStringAssembler(compiler::CodeAssemblerState* state,
    1513             :                                    Node* string);
    1514             : 
    1515             :   // Converts flat cons, thin, and sliced strings and returns the direct
    1516             :   // string. The result can be either a sequential or external string.
    1517             :   Node* TryToDirect(Label* if_bailout);
    1518             : 
    1519             :   // Returns a pointer to the beginning of the string data.
    1520             :   Node* PointerToData(Label* if_bailout) {
    1521        1892 :     return TryToSequential(PTR_TO_DATA, if_bailout);
    1522             :   }
    1523             : 
    1524             :   // Returns a pointer that, offset-wise, looks like a String.
    1525             :   Node* PointerToString(Label* if_bailout) {
    1526         817 :     return TryToSequential(PTR_TO_STRING, if_bailout);
    1527             :   }
    1528             : 
    1529             :   Node* string() { return var_string_.value(); }
    1530        3526 :   Node* instance_type() { return var_instance_type_.value(); }
    1531        3139 :   Node* offset() { return var_offset_.value(); }
    1532        3612 :   Node* is_external() { return var_is_external_.value(); }
    1533             : 
    1534             :  private:
    1535             :   Node* TryToSequential(StringPointerKind ptr_kind, Label* if_bailout);
    1536             : 
    1537             :   Variable var_string_;
    1538             :   Variable var_instance_type_;
    1539             :   Variable var_offset_;
    1540             :   Variable var_is_external_;
    1541             : };
    1542             : 
    1543             : #ifdef DEBUG
    1544             : #define CSA_ASSERT(csa, x) \
    1545             :   (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__)
    1546             : #define CSA_ASSERT_JS_ARGC_OP(csa, Op, op, expected)             \
    1547             :   (csa)->Assert(                                                 \
    1548             :       [&] {                                                      \
    1549             :         compiler::Node* const argc =                             \
    1550             :             (csa)->Parameter(Descriptor::kActualArgumentsCount); \
    1551             :         return (csa)->Op(argc, (csa)->Int32Constant(expected));  \
    1552             :       },                                                         \
    1553             :       "argc " #op " " #expected, __FILE__, __LINE__)
    1554             : 
    1555             : #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) \
    1556             :   CSA_ASSERT_JS_ARGC_OP(csa, Word32Equal, ==, expected)
    1557             : 
    1558             : #define BIND(label) Bind(label, {#label, __FILE__, __LINE__})
    1559             : #define VARIABLE(name, ...) \
    1560             :   Variable name(this, {#name, __FILE__, __LINE__}, __VA_ARGS__);
    1561             : 
    1562             : #else  // DEBUG
    1563             : #define CSA_ASSERT(csa, x) ((void)0)
    1564             : #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) ((void)0)
    1565             : #define BIND(label) Bind(label);
    1566             : #define VARIABLE(name, ...) Variable name(this, __VA_ARGS__);
    1567             : #endif  // DEBUG
    1568             : 
    1569             : #ifdef ENABLE_SLOW_DCHECKS
    1570             : #define CSA_SLOW_ASSERT(csa, x)                                 \
    1571             :   if (FLAG_enable_slow_asserts) {                               \
    1572             :     (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__); \
    1573             :   }
    1574             : #else
    1575             : #define CSA_SLOW_ASSERT(csa, x) ((void)0)
    1576             : #endif
    1577             : 
    1578             : DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
    1579             : 
    1580             : }  // namespace internal
    1581             : }  // namespace v8
    1582             : #endif  // V8_CODE_STUB_ASSEMBLER_H_

Generated by: LCOV version 1.10