Home | History | Annotate | Download | only in src
      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 StatsCounter;
     19 class StubCache;
     20 
     21 enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
     22 
     23 #define HEAP_CONSTANT_LIST(V)                 \
     24   V(BooleanMap, BooleanMap)                   \
     25   V(CodeMap, CodeMap)                         \
     26   V(empty_string, EmptyString)                \
     27   V(EmptyFixedArray, EmptyFixedArray)         \
     28   V(FalseValue, False)                        \
     29   V(FixedArrayMap, FixedArrayMap)             \
     30   V(FixedCOWArrayMap, FixedCOWArrayMap)       \
     31   V(FixedDoubleArrayMap, FixedDoubleArrayMap) \
     32   V(HeapNumberMap, HeapNumberMap)             \
     33   V(MinusZeroValue, MinusZero)                \
     34   V(NanValue, Nan)                            \
     35   V(NullValue, Null)                          \
     36   V(TheHoleValue, TheHole)                    \
     37   V(TrueValue, True)                          \
     38   V(UndefinedValue, Undefined)
     39 
     40 // Provides JavaScript-specific "macro-assembler" functionality on top of the
     41 // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
     42 // it's possible to add JavaScript-specific useful CodeAssembler "macros"
     43 // without modifying files in the compiler directory (and requiring a review
     44 // from a compiler directory OWNER).
     45 class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
     46  public:
     47   // Create with CallStub linkage.
     48   // |result_size| specifies the number of results returned by the stub.
     49   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
     50   CodeStubAssembler(Isolate* isolate, Zone* zone,
     51                     const CallInterfaceDescriptor& descriptor,
     52                     Code::Flags flags, const char* name,
     53                     size_t result_size = 1);
     54 
     55   // Create with JSCall linkage.
     56   CodeStubAssembler(Isolate* isolate, Zone* zone, int parameter_count,
     57                     Code::Flags flags, const char* name);
     58 
     59   enum AllocationFlag : uint8_t {
     60     kNone = 0,
     61     kDoubleAlignment = 1,
     62     kPretenured = 1 << 1
     63   };
     64 
     65   typedef base::Flags<AllocationFlag> AllocationFlags;
     66 
     67   // TODO(ishell): Fix all loads/stores from arrays by int32 offsets/indices
     68   // and eventually remove INTEGER_PARAMETERS in favour of INTPTR_PARAMETERS.
     69   enum ParameterMode { INTEGER_PARAMETERS, SMI_PARAMETERS, INTPTR_PARAMETERS };
     70 
     71   // On 32-bit platforms, there is a slight performance advantage to doing all
     72   // of the array offset/index arithmetic with SMIs, since it's possible
     73   // to save a few tag/untag operations without paying an extra expense when
     74   // calculating array offset (the smi math can be folded away) and there are
     75   // fewer live ranges. Thus only convert indices to untagged value on 64-bit
     76   // platforms.
     77   ParameterMode OptimalParameterMode() const {
     78     return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS;
     79   }
     80 
     81   compiler::Node* UntagParameter(compiler::Node* value, ParameterMode mode) {
     82     if (mode != SMI_PARAMETERS) value = SmiUntag(value);
     83     return value;
     84   }
     85 
     86   compiler::Node* TagParameter(compiler::Node* value, ParameterMode mode) {
     87     if (mode != SMI_PARAMETERS) value = SmiTag(value);
     88     return value;
     89   }
     90 
     91   compiler::Node* NoContextConstant();
     92 #define HEAP_CONSTANT_ACCESSOR(rootName, name) compiler::Node* name##Constant();
     93   HEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR)
     94 #undef HEAP_CONSTANT_ACCESSOR
     95 
     96 #define HEAP_CONSTANT_TEST(rootName, name) \
     97   compiler::Node* Is##name(compiler::Node* value);
     98   HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST)
     99 #undef HEAP_CONSTANT_TEST
    100 
    101   compiler::Node* HashSeed();
    102   compiler::Node* StaleRegisterConstant();
    103 
    104   compiler::Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
    105 
    106   compiler::Node* IntPtrAddFoldConstants(compiler::Node* left,
    107                                          compiler::Node* right);
    108   compiler::Node* IntPtrSubFoldConstants(compiler::Node* left,
    109                                          compiler::Node* right);
    110   // Round the 32bits payload of the provided word up to the next power of two.
    111   compiler::Node* IntPtrRoundUpToPowerOfTwo32(compiler::Node* value);
    112   compiler::Node* IntPtrMax(compiler::Node* left, compiler::Node* right);
    113 
    114   // Float64 operations.
    115   compiler::Node* Float64Ceil(compiler::Node* x);
    116   compiler::Node* Float64Floor(compiler::Node* x);
    117   compiler::Node* Float64Round(compiler::Node* x);
    118   compiler::Node* Float64RoundToEven(compiler::Node* x);
    119   compiler::Node* Float64Trunc(compiler::Node* x);
    120 
    121   // Tag a Word as a Smi value.
    122   compiler::Node* SmiTag(compiler::Node* value);
    123   // Untag a Smi value as a Word.
    124   compiler::Node* SmiUntag(compiler::Node* value);
    125 
    126   // Smi conversions.
    127   compiler::Node* SmiToFloat64(compiler::Node* value);
    128   compiler::Node* SmiFromWord(compiler::Node* value) { return SmiTag(value); }
    129   compiler::Node* SmiFromWord32(compiler::Node* value);
    130   compiler::Node* SmiToWord(compiler::Node* value) { return SmiUntag(value); }
    131   compiler::Node* SmiToWord32(compiler::Node* value);
    132 
    133   // Smi operations.
    134   compiler::Node* SmiAdd(compiler::Node* a, compiler::Node* b);
    135   compiler::Node* SmiSub(compiler::Node* a, compiler::Node* b);
    136   compiler::Node* SmiEqual(compiler::Node* a, compiler::Node* b);
    137   compiler::Node* SmiAbove(compiler::Node* a, compiler::Node* b);
    138   compiler::Node* SmiAboveOrEqual(compiler::Node* a, compiler::Node* b);
    139   compiler::Node* SmiBelow(compiler::Node* a, compiler::Node* b);
    140   compiler::Node* SmiLessThan(compiler::Node* a, compiler::Node* b);
    141   compiler::Node* SmiLessThanOrEqual(compiler::Node* a, compiler::Node* b);
    142   compiler::Node* SmiMax(compiler::Node* a, compiler::Node* b);
    143   compiler::Node* SmiMin(compiler::Node* a, compiler::Node* b);
    144   // Computes a % b for Smi inputs a and b; result is not necessarily a Smi.
    145   compiler::Node* SmiMod(compiler::Node* a, compiler::Node* b);
    146   // Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
    147   compiler::Node* SmiMul(compiler::Node* a, compiler::Node* b);
    148   compiler::Node* SmiOr(compiler::Node* a, compiler::Node* b) {
    149     return BitcastWordToTaggedSigned(
    150         WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b)));
    151   }
    152 
    153   // Smi | HeapNumber operations.
    154   compiler::Node* NumberInc(compiler::Node* value);
    155 
    156   // Allocate an object of the given size.
    157   compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone);
    158   compiler::Node* Allocate(int size, AllocationFlags flags = kNone);
    159   compiler::Node* InnerAllocate(compiler::Node* previous, int offset);
    160   compiler::Node* InnerAllocate(compiler::Node* previous,
    161                                 compiler::Node* offset);
    162   compiler::Node* IsRegularHeapObjectSize(compiler::Node* size);
    163 
    164   typedef std::function<compiler::Node*()> ConditionBody;
    165   void Assert(ConditionBody condition_body, const char* string = nullptr,
    166               const char* file = nullptr, int line = 0);
    167 
    168   // Check a value for smi-ness
    169   compiler::Node* TaggedIsSmi(compiler::Node* a);
    170   // Check that the value is a non-negative smi.
    171   compiler::Node* WordIsPositiveSmi(compiler::Node* a);
    172   // Check that a word has a word-aligned address.
    173   compiler::Node* WordIsWordAligned(compiler::Node* word);
    174   compiler::Node* WordIsPowerOfTwo(compiler::Node* value);
    175 
    176   void BranchIfSmiEqual(compiler::Node* a, compiler::Node* b, Label* if_true,
    177                         Label* if_false) {
    178     Branch(SmiEqual(a, b), if_true, if_false);
    179   }
    180 
    181   void BranchIfSmiLessThan(compiler::Node* a, compiler::Node* b, Label* if_true,
    182                            Label* if_false) {
    183     Branch(SmiLessThan(a, b), if_true, if_false);
    184   }
    185 
    186   void BranchIfSmiLessThanOrEqual(compiler::Node* a, compiler::Node* b,
    187                                   Label* if_true, Label* if_false) {
    188     Branch(SmiLessThanOrEqual(a, b), if_true, if_false);
    189   }
    190 
    191   void BranchIfFloat64IsNaN(compiler::Node* value, Label* if_true,
    192                             Label* if_false) {
    193     Branch(Float64Equal(value, value), if_false, if_true);
    194   }
    195 
    196   // Branches to {if_true} if ToBoolean applied to {value} yields true,
    197   // otherwise goes to {if_false}.
    198   void BranchIfToBooleanIsTrue(compiler::Node* value, Label* if_true,
    199                                Label* if_false);
    200 
    201   void BranchIfSimd128Equal(compiler::Node* lhs, compiler::Node* lhs_map,
    202                             compiler::Node* rhs, compiler::Node* rhs_map,
    203                             Label* if_equal, Label* if_notequal);
    204   void BranchIfSimd128Equal(compiler::Node* lhs, compiler::Node* rhs,
    205                             Label* if_equal, Label* if_notequal) {
    206     BranchIfSimd128Equal(lhs, LoadMap(lhs), rhs, LoadMap(rhs), if_equal,
    207                          if_notequal);
    208   }
    209 
    210   void BranchIfJSReceiver(compiler::Node* object, Label* if_true,
    211                           Label* if_false);
    212   void BranchIfJSObject(compiler::Node* object, Label* if_true,
    213                         Label* if_false);
    214   void BranchIfFastJSArray(compiler::Node* object, compiler::Node* context,
    215                            Label* if_true, Label* if_false);
    216 
    217   // Load value from current frame by given offset in bytes.
    218   compiler::Node* LoadFromFrame(int offset,
    219                                 MachineType rep = MachineType::AnyTagged());
    220   // Load value from current parent frame by given offset in bytes.
    221   compiler::Node* LoadFromParentFrame(
    222       int offset, MachineType rep = MachineType::AnyTagged());
    223 
    224   // Load an object pointer from a buffer that isn't in the heap.
    225   compiler::Node* LoadBufferObject(compiler::Node* buffer, int offset,
    226                                    MachineType rep = MachineType::AnyTagged());
    227   // Load a field from an object on the heap.
    228   compiler::Node* LoadObjectField(compiler::Node* object, int offset,
    229                                   MachineType rep = MachineType::AnyTagged());
    230   compiler::Node* LoadObjectField(compiler::Node* object,
    231                                   compiler::Node* offset,
    232                                   MachineType rep = MachineType::AnyTagged());
    233   // Load a SMI field and untag it.
    234   compiler::Node* LoadAndUntagObjectField(compiler::Node* object, int offset);
    235   // Load a SMI field, untag it, and convert to Word32.
    236   compiler::Node* LoadAndUntagToWord32ObjectField(compiler::Node* object,
    237                                                   int offset);
    238   // Load a SMI and untag it.
    239   compiler::Node* LoadAndUntagSmi(compiler::Node* base, int index);
    240   // Load a SMI root, untag it, and convert to Word32.
    241   compiler::Node* LoadAndUntagToWord32Root(Heap::RootListIndex root_index);
    242 
    243   // Load the floating point value of a HeapNumber.
    244   compiler::Node* LoadHeapNumberValue(compiler::Node* object);
    245   // Load the Map of an HeapObject.
    246   compiler::Node* LoadMap(compiler::Node* object);
    247   // Load the instance type of an HeapObject.
    248   compiler::Node* LoadInstanceType(compiler::Node* object);
    249   // Compare the instance the type of the object against the provided one.
    250   compiler::Node* HasInstanceType(compiler::Node* object, InstanceType type);
    251   // Load the properties backing store of a JSObject.
    252   compiler::Node* LoadProperties(compiler::Node* object);
    253   // Load the elements backing store of a JSObject.
    254   compiler::Node* LoadElements(compiler::Node* object);
    255   // Load the length of a JSArray instance.
    256   compiler::Node* LoadJSArrayLength(compiler::Node* array);
    257   // Load the length of a fixed array base instance.
    258   compiler::Node* LoadFixedArrayBaseLength(compiler::Node* array);
    259   // Load the length of a fixed array base instance.
    260   compiler::Node* LoadAndUntagFixedArrayBaseLength(compiler::Node* array);
    261   // Load the bit field of a Map.
    262   compiler::Node* LoadMapBitField(compiler::Node* map);
    263   // Load bit field 2 of a map.
    264   compiler::Node* LoadMapBitField2(compiler::Node* map);
    265   // Load bit field 3 of a map.
    266   compiler::Node* LoadMapBitField3(compiler::Node* map);
    267   // Load the instance type of a map.
    268   compiler::Node* LoadMapInstanceType(compiler::Node* map);
    269   // Load the ElementsKind of a map.
    270   compiler::Node* LoadMapElementsKind(compiler::Node* map);
    271   // Load the instance descriptors of a map.
    272   compiler::Node* LoadMapDescriptors(compiler::Node* map);
    273   // Load the prototype of a map.
    274   compiler::Node* LoadMapPrototype(compiler::Node* map);
    275   // Load the prototype info of a map. The result has to be checked if it is a
    276   // prototype info object or not.
    277   compiler::Node* LoadMapPrototypeInfo(compiler::Node* map,
    278                                        Label* if_has_no_proto_info);
    279   // Load the instance size of a Map.
    280   compiler::Node* LoadMapInstanceSize(compiler::Node* map);
    281   // Load the inobject properties count of a Map (valid only for JSObjects).
    282   compiler::Node* LoadMapInobjectProperties(compiler::Node* map);
    283   // Load the constructor function index of a Map (only for primitive maps).
    284   compiler::Node* LoadMapConstructorFunctionIndex(compiler::Node* map);
    285   // Load the constructor of a Map (equivalent to Map::GetConstructor()).
    286   compiler::Node* LoadMapConstructor(compiler::Node* map);
    287   // Check if the map is set for slow properties.
    288   compiler::Node* IsDictionaryMap(compiler::Node* map);
    289 
    290   // Load the hash field of a name as an uint32 value.
    291   compiler::Node* LoadNameHashField(compiler::Node* name);
    292   // Load the hash value of a name as an uint32 value.
    293   // If {if_hash_not_computed} label is specified then it also checks if
    294   // hash is actually computed.
    295   compiler::Node* LoadNameHash(compiler::Node* name,
    296                                Label* if_hash_not_computed = nullptr);
    297 
    298   // Load length field of a String object.
    299   compiler::Node* LoadStringLength(compiler::Node* object);
    300   // Load value field of a JSValue object.
    301   compiler::Node* LoadJSValueValue(compiler::Node* object);
    302   // Load value field of a WeakCell object.
    303   compiler::Node* LoadWeakCellValueUnchecked(compiler::Node* weak_cell);
    304   compiler::Node* LoadWeakCellValue(compiler::Node* weak_cell,
    305                                     Label* if_cleared = nullptr);
    306 
    307   // Load an array element from a FixedArray.
    308   compiler::Node* LoadFixedArrayElement(
    309       compiler::Node* object, compiler::Node* index, int additional_offset = 0,
    310       ParameterMode parameter_mode = INTEGER_PARAMETERS);
    311   // Load an array element from a FixedArray, untag it and return it as Word32.
    312   compiler::Node* LoadAndUntagToWord32FixedArrayElement(
    313       compiler::Node* object, compiler::Node* index, int additional_offset = 0,
    314       ParameterMode parameter_mode = INTEGER_PARAMETERS);
    315   // Load an array element from a FixedDoubleArray.
    316   compiler::Node* LoadFixedDoubleArrayElement(
    317       compiler::Node* object, compiler::Node* index, MachineType machine_type,
    318       int additional_offset = 0,
    319       ParameterMode parameter_mode = INTEGER_PARAMETERS,
    320       Label* if_hole = nullptr);
    321 
    322   // Load Float64 value by |base| + |offset| address. If the value is a double
    323   // hole then jump to |if_hole|. If |machine_type| is None then only the hole
    324   // check is generated.
    325   compiler::Node* LoadDoubleWithHoleCheck(
    326       compiler::Node* base, compiler::Node* offset, Label* if_hole,
    327       MachineType machine_type = MachineType::Float64());
    328   compiler::Node* LoadFixedTypedArrayElement(
    329       compiler::Node* data_pointer, compiler::Node* index_node,
    330       ElementsKind elements_kind,
    331       ParameterMode parameter_mode = INTEGER_PARAMETERS);
    332 
    333   // Context manipulation
    334   compiler::Node* LoadContextElement(compiler::Node* context, int slot_index);
    335   compiler::Node* LoadContextElement(compiler::Node* context,
    336                                      compiler::Node* slot_index);
    337   compiler::Node* StoreContextElement(compiler::Node* context, int slot_index,
    338                                       compiler::Node* value);
    339   compiler::Node* StoreContextElement(compiler::Node* context,
    340                                       compiler::Node* slot_index,
    341                                       compiler::Node* value);
    342   compiler::Node* LoadNativeContext(compiler::Node* context);
    343 
    344   compiler::Node* LoadJSArrayElementsMap(ElementsKind kind,
    345                                          compiler::Node* native_context);
    346 
    347   // Store the floating point value of a HeapNumber.
    348   compiler::Node* StoreHeapNumberValue(compiler::Node* object,
    349                                        compiler::Node* value);
    350   // Store a field to an object on the heap.
    351   compiler::Node* StoreObjectField(
    352       compiler::Node* object, int offset, compiler::Node* value);
    353   compiler::Node* StoreObjectField(compiler::Node* object,
    354                                    compiler::Node* offset,
    355                                    compiler::Node* value);
    356   compiler::Node* StoreObjectFieldNoWriteBarrier(
    357       compiler::Node* object, int offset, compiler::Node* value,
    358       MachineRepresentation rep = MachineRepresentation::kTagged);
    359   compiler::Node* StoreObjectFieldNoWriteBarrier(
    360       compiler::Node* object, compiler::Node* offset, compiler::Node* value,
    361       MachineRepresentation rep = MachineRepresentation::kTagged);
    362   // Store the Map of an HeapObject.
    363   compiler::Node* StoreMapNoWriteBarrier(compiler::Node* object,
    364                                          compiler::Node* map);
    365   compiler::Node* StoreObjectFieldRoot(compiler::Node* object, int offset,
    366                                        Heap::RootListIndex root);
    367   // Store an array element to a FixedArray.
    368   compiler::Node* StoreFixedArrayElement(
    369       compiler::Node* object, int index, compiler::Node* value,
    370       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    371       ParameterMode parameter_mode = INTEGER_PARAMETERS) {
    372     return StoreFixedArrayElement(object, Int32Constant(index), value,
    373                                   barrier_mode, parameter_mode);
    374   }
    375 
    376   compiler::Node* StoreFixedArrayElement(
    377       compiler::Node* object, compiler::Node* index, compiler::Node* value,
    378       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    379       ParameterMode parameter_mode = INTEGER_PARAMETERS);
    380 
    381   compiler::Node* StoreFixedDoubleArrayElement(
    382       compiler::Node* object, compiler::Node* index, compiler::Node* value,
    383       ParameterMode parameter_mode = INTEGER_PARAMETERS);
    384 
    385   void StoreFieldsNoWriteBarrier(compiler::Node* start_address,
    386                                  compiler::Node* end_address,
    387                                  compiler::Node* value);
    388 
    389   // Allocate a HeapNumber without initializing its value.
    390   compiler::Node* AllocateHeapNumber(MutableMode mode = IMMUTABLE);
    391   // Allocate a HeapNumber with a specific value.
    392   compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value,
    393                                               MutableMode mode = IMMUTABLE);
    394   // Allocate a SeqOneByteString with the given length.
    395   compiler::Node* AllocateSeqOneByteString(int length,
    396                                            AllocationFlags flags = kNone);
    397   compiler::Node* AllocateSeqOneByteString(
    398       compiler::Node* context, compiler::Node* length,
    399       ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
    400   // Allocate a SeqTwoByteString with the given length.
    401   compiler::Node* AllocateSeqTwoByteString(int length,
    402                                            AllocationFlags flags = kNone);
    403   compiler::Node* AllocateSeqTwoByteString(
    404       compiler::Node* context, compiler::Node* length,
    405       ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
    406 
    407   // Allocate a SlicedOneByteString with the given length, parent and offset.
    408   // |length| and |offset| are expected to be tagged.
    409   compiler::Node* AllocateSlicedOneByteString(compiler::Node* length,
    410                                               compiler::Node* parent,
    411                                               compiler::Node* offset);
    412   // Allocate a SlicedTwoByteString with the given length, parent and offset.
    413   // |length| and |offset| are expected to be tagged.
    414   compiler::Node* AllocateSlicedTwoByteString(compiler::Node* length,
    415                                               compiler::Node* parent,
    416                                               compiler::Node* offset);
    417 
    418   // Allocate a one-byte ConsString with the given length, first and second
    419   // parts. |length| is expected to be tagged, and |first| and |second| are
    420   // expected to be one-byte strings.
    421   compiler::Node* AllocateOneByteConsString(compiler::Node* length,
    422                                             compiler::Node* first,
    423                                             compiler::Node* second,
    424                                             AllocationFlags flags = kNone);
    425   // Allocate a two-byte ConsString with the given length, first and second
    426   // parts. |length| is expected to be tagged, and |first| and |second| are
    427   // expected to be two-byte strings.
    428   compiler::Node* AllocateTwoByteConsString(compiler::Node* length,
    429                                             compiler::Node* first,
    430                                             compiler::Node* second,
    431                                             AllocationFlags flags = kNone);
    432 
    433   // Allocate an appropriate one- or two-byte ConsString with the first and
    434   // second parts specified by |first| and |second|.
    435   compiler::Node* NewConsString(compiler::Node* context, compiler::Node* length,
    436                                 compiler::Node* left, compiler::Node* right,
    437                                 AllocationFlags flags = kNone);
    438 
    439   // Allocate a RegExpResult with the given length (the number of captures,
    440   // including the match itself), index (the index where the match starts),
    441   // and input string. |length| and |index| are expected to be tagged, and
    442   // |input| must be a string.
    443   compiler::Node* AllocateRegExpResult(compiler::Node* context,
    444                                        compiler::Node* length,
    445                                        compiler::Node* index,
    446                                        compiler::Node* input);
    447 
    448   compiler::Node* AllocateNameDictionary(int capacity);
    449   compiler::Node* AllocateNameDictionary(compiler::Node* capacity);
    450 
    451   compiler::Node* AllocateJSObjectFromMap(compiler::Node* map,
    452                                           compiler::Node* properties = nullptr,
    453                                           compiler::Node* elements = nullptr);
    454 
    455   void InitializeJSObjectFromMap(compiler::Node* object, compiler::Node* map,
    456                                  compiler::Node* size,
    457                                  compiler::Node* properties = nullptr,
    458                                  compiler::Node* elements = nullptr);
    459 
    460   void InitializeJSObjectBody(compiler::Node* object, compiler::Node* map,
    461                               compiler::Node* size,
    462                               int start_offset = JSObject::kHeaderSize);
    463 
    464   // Allocate a JSArray without elements and initialize the header fields.
    465   compiler::Node* AllocateUninitializedJSArrayWithoutElements(
    466       ElementsKind kind, compiler::Node* array_map, compiler::Node* length,
    467       compiler::Node* allocation_site);
    468   // Allocate and return a JSArray with initialized header fields and its
    469   // uninitialized elements.
    470   // The ParameterMode argument is only used for the capacity parameter.
    471   std::pair<compiler::Node*, compiler::Node*>
    472   AllocateUninitializedJSArrayWithElements(
    473       ElementsKind kind, compiler::Node* array_map, compiler::Node* length,
    474       compiler::Node* allocation_site, compiler::Node* capacity,
    475       ParameterMode capacity_mode = INTEGER_PARAMETERS);
    476   // Allocate a JSArray and fill elements with the hole.
    477   // The ParameterMode argument is only used for the capacity parameter.
    478   compiler::Node* AllocateJSArray(
    479       ElementsKind kind, compiler::Node* array_map, compiler::Node* capacity,
    480       compiler::Node* length, compiler::Node* allocation_site = nullptr,
    481       ParameterMode capacity_mode = INTEGER_PARAMETERS);
    482 
    483   compiler::Node* AllocateFixedArray(ElementsKind kind,
    484                                      compiler::Node* capacity,
    485                                      ParameterMode mode = INTEGER_PARAMETERS,
    486                                      AllocationFlags flags = kNone);
    487 
    488   // Perform CreateArrayIterator (ES6 #sec-createarrayiterator).
    489   compiler::Node* CreateArrayIterator(compiler::Node* array,
    490                                       compiler::Node* array_map,
    491                                       compiler::Node* array_type,
    492                                       compiler::Node* context,
    493                                       IterationKind mode);
    494 
    495   compiler::Node* AllocateJSArrayIterator(compiler::Node* array,
    496                                           compiler::Node* array_map,
    497                                           compiler::Node* map);
    498 
    499   void FillFixedArrayWithValue(ElementsKind kind, compiler::Node* array,
    500                                compiler::Node* from_index,
    501                                compiler::Node* to_index,
    502                                Heap::RootListIndex value_root_index,
    503                                ParameterMode mode = INTEGER_PARAMETERS);
    504 
    505   // Copies all elements from |from_array| of |length| size to
    506   // |to_array| of the same size respecting the elements kind.
    507   void CopyFixedArrayElements(
    508       ElementsKind kind, compiler::Node* from_array, compiler::Node* to_array,
    509       compiler::Node* length,
    510       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    511       ParameterMode mode = INTEGER_PARAMETERS) {
    512     CopyFixedArrayElements(kind, from_array, kind, to_array, length, length,
    513                            barrier_mode, mode);
    514   }
    515 
    516   // Copies |element_count| elements from |from_array| to |to_array| of
    517   // |capacity| size respecting both array's elements kinds.
    518   void CopyFixedArrayElements(
    519       ElementsKind from_kind, compiler::Node* from_array, ElementsKind to_kind,
    520       compiler::Node* to_array, compiler::Node* element_count,
    521       compiler::Node* capacity,
    522       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
    523       ParameterMode mode = INTEGER_PARAMETERS);
    524 
    525   // Copies |character_count| elements from |from_string| to |to_string|
    526   // starting at the |from_index|'th character. |from_string| and |to_string|
    527   // can either be one-byte strings or two-byte strings, although if
    528   // |from_string| is two-byte, then |to_string| must be two-byte.
    529   // |from_index|, |to_index| and |character_count| must be either Smis or
    530   // intptr_ts depending on |mode| s.t. 0 <= |from_index| <= |from_index| +
    531   // |character_count| <= from_string.length and 0 <= |to_index| <= |to_index| +
    532   // |character_count| <= to_string.length.
    533   void CopyStringCharacters(compiler::Node* from_string,
    534                             compiler::Node* to_string,
    535                             compiler::Node* from_index,
    536                             compiler::Node* to_index,
    537                             compiler::Node* character_count,
    538                             String::Encoding from_encoding,
    539                             String::Encoding to_encoding, ParameterMode mode);
    540 
    541   // Loads an element from |array| of |from_kind| elements by given |offset|
    542   // (NOTE: not index!), does a hole check if |if_hole| is provided and
    543   // converts the value so that it becomes ready for storing to array of
    544   // |to_kind| elements.
    545   compiler::Node* LoadElementAndPrepareForStore(compiler::Node* array,
    546                                                 compiler::Node* offset,
    547                                                 ElementsKind from_kind,
    548                                                 ElementsKind to_kind,
    549                                                 Label* if_hole);
    550 
    551   compiler::Node* CalculateNewElementsCapacity(
    552       compiler::Node* old_capacity, ParameterMode mode = INTEGER_PARAMETERS);
    553 
    554   // Tries to grow the |elements| array of given |object| to store the |key|
    555   // or bails out if the growing gap is too big. Returns new elements.
    556   compiler::Node* TryGrowElementsCapacity(compiler::Node* object,
    557                                           compiler::Node* elements,
    558                                           ElementsKind kind,
    559                                           compiler::Node* key, Label* bailout);
    560 
    561   // Tries to grow the |capacity|-length |elements| array of given |object|
    562   // to store the |key| or bails out if the growing gap is too big. Returns
    563   // new elements.
    564   compiler::Node* TryGrowElementsCapacity(compiler::Node* object,
    565                                           compiler::Node* elements,
    566                                           ElementsKind kind,
    567                                           compiler::Node* key,
    568                                           compiler::Node* capacity,
    569                                           ParameterMode mode, Label* bailout);
    570 
    571   // Grows elements capacity of given object. Returns new elements.
    572   compiler::Node* GrowElementsCapacity(
    573       compiler::Node* object, compiler::Node* elements, ElementsKind from_kind,
    574       ElementsKind to_kind, compiler::Node* capacity,
    575       compiler::Node* new_capacity, ParameterMode mode, Label* bailout);
    576 
    577   // Allocation site manipulation
    578   void InitializeAllocationMemento(compiler::Node* base_allocation,
    579                                    int base_allocation_size,
    580                                    compiler::Node* allocation_site);
    581 
    582   compiler::Node* TryTaggedToFloat64(compiler::Node* value,
    583                                      Label* if_valueisnotnumber);
    584   compiler::Node* TruncateTaggedToFloat64(compiler::Node* context,
    585                                           compiler::Node* value);
    586   compiler::Node* TruncateTaggedToWord32(compiler::Node* context,
    587                                          compiler::Node* value);
    588   // Truncate the floating point value of a HeapNumber to an Int32.
    589   compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object);
    590 
    591   // Conversions.
    592   compiler::Node* ChangeFloat64ToTagged(compiler::Node* value);
    593   compiler::Node* ChangeInt32ToTagged(compiler::Node* value);
    594   compiler::Node* ChangeUint32ToTagged(compiler::Node* value);
    595 
    596   // Type conversions.
    597   // Throws a TypeError for {method_name} if {value} is not coercible to Object,
    598   // or returns the {value} converted to a String otherwise.
    599   compiler::Node* ToThisString(compiler::Node* context, compiler::Node* value,
    600                                char const* method_name);
    601   // Throws a TypeError for {method_name} if {value} is neither of the given
    602   // {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or
    603   // returns the {value} (or wrapped value) otherwise.
    604   compiler::Node* ToThisValue(compiler::Node* context, compiler::Node* value,
    605                               PrimitiveType primitive_type,
    606                               char const* method_name);
    607 
    608   // Throws a TypeError for {method_name} if {value} is not of the given
    609   // instance type. Returns {value}'s map.
    610   compiler::Node* ThrowIfNotInstanceType(compiler::Node* context,
    611                                          compiler::Node* value,
    612                                          InstanceType instance_type,
    613                                          char const* method_name);
    614 
    615   // Type checks.
    616   // Check whether the map is for an object with special properties, such as a
    617   // JSProxy or an object with interceptors.
    618   compiler::Node* IsSpecialReceiverMap(compiler::Node* map);
    619   compiler::Node* IsSpecialReceiverInstanceType(compiler::Node* instance_type);
    620   compiler::Node* IsStringInstanceType(compiler::Node* instance_type);
    621   compiler::Node* IsString(compiler::Node* object);
    622   compiler::Node* IsJSObject(compiler::Node* object);
    623   compiler::Node* IsJSGlobalProxy(compiler::Node* object);
    624   compiler::Node* IsJSReceiverInstanceType(compiler::Node* instance_type);
    625   compiler::Node* IsJSReceiver(compiler::Node* object);
    626   compiler::Node* IsMap(compiler::Node* object);
    627   compiler::Node* IsCallableMap(compiler::Node* map);
    628   compiler::Node* IsName(compiler::Node* object);
    629   compiler::Node* IsJSValue(compiler::Node* object);
    630   compiler::Node* IsJSArray(compiler::Node* object);
    631   compiler::Node* IsNativeContext(compiler::Node* object);
    632   compiler::Node* IsWeakCell(compiler::Node* object);
    633   compiler::Node* IsFixedDoubleArray(compiler::Node* object);
    634   compiler::Node* IsHashTable(compiler::Node* object);
    635   compiler::Node* IsDictionary(compiler::Node* object);
    636   compiler::Node* IsUnseededNumberDictionary(compiler::Node* object);
    637 
    638   // ElementsKind helpers:
    639   compiler::Node* IsFastElementsKind(compiler::Node* elements_kind);
    640   compiler::Node* IsHoleyFastElementsKind(compiler::Node* elements_kind);
    641 
    642   // String helpers.
    643   // Load a character from a String (might flatten a ConsString).
    644   compiler::Node* StringCharCodeAt(compiler::Node* string,
    645                                    compiler::Node* smi_index);
    646   // Return the single character string with only {code}.
    647   compiler::Node* StringFromCharCode(compiler::Node* code);
    648   // Return a new string object which holds a substring containing the range
    649   // [from,to[ of string.  |from| and |to| are expected to be tagged.
    650   compiler::Node* SubString(compiler::Node* context, compiler::Node* string,
    651                             compiler::Node* from, compiler::Node* to);
    652 
    653   // Return a new string object produced by concatenating |first| with |second|.
    654   compiler::Node* StringAdd(compiler::Node* context, compiler::Node* first,
    655                             compiler::Node* second,
    656                             AllocationFlags flags = kNone);
    657 
    658   // Return the first index >= {from} at which {needle_char} was found in
    659   // {string}, or -1 if such an index does not exist. The returned value is
    660   // a Smi, {string} is expected to be a String, {needle_char} is an intptr,
    661   // and {from} is expected to be tagged.
    662   compiler::Node* StringIndexOfChar(compiler::Node* context,
    663                                     compiler::Node* string,
    664                                     compiler::Node* needle_char,
    665                                     compiler::Node* from);
    666 
    667   compiler::Node* StringFromCodePoint(compiler::Node* codepoint,
    668                                       UnicodeEncoding encoding);
    669 
    670   // Type conversion helpers.
    671   // Convert a String to a Number.
    672   compiler::Node* StringToNumber(compiler::Node* context,
    673                                  compiler::Node* input);
    674   compiler::Node* NumberToString(compiler::Node* context,
    675                                  compiler::Node* input);
    676   // Convert an object to a name.
    677   compiler::Node* ToName(compiler::Node* context, compiler::Node* input);
    678   // Convert a Non-Number object to a Number.
    679   compiler::Node* NonNumberToNumber(compiler::Node* context,
    680                                     compiler::Node* input);
    681   // Convert any object to a Number.
    682   compiler::Node* ToNumber(compiler::Node* context, compiler::Node* input);
    683 
    684   // Convert any object to a String.
    685   compiler::Node* ToString(compiler::Node* context, compiler::Node* input);
    686 
    687   // Convert any object to a Primitive.
    688   compiler::Node* JSReceiverToPrimitive(compiler::Node* context,
    689                                         compiler::Node* input);
    690 
    691   // Convert a String to a flat String.
    692   compiler::Node* FlattenString(compiler::Node* string);
    693 
    694   enum ToIntegerTruncationMode {
    695     kNoTruncation,
    696     kTruncateMinusZero,
    697   };
    698 
    699   // Convert any object to an Integer.
    700   compiler::Node* ToInteger(compiler::Node* context, compiler::Node* input,
    701                             ToIntegerTruncationMode mode = kNoTruncation);
    702 
    703   // Returns a node that contains a decoded (unsigned!) value of a bit
    704   // field |T| in |word32|. Returns result as an uint32 node.
    705   template <typename T>
    706   compiler::Node* DecodeWord32(compiler::Node* word32) {
    707     return DecodeWord32(word32, T::kShift, T::kMask);
    708   }
    709 
    710   // Returns a node that contains a decoded (unsigned!) value of a bit
    711   // field |T| in |word|. Returns result as a word-size node.
    712   template <typename T>
    713   compiler::Node* DecodeWord(compiler::Node* word) {
    714     return DecodeWord(word, T::kShift, T::kMask);
    715   }
    716 
    717   // Returns a node that contains a decoded (unsigned!) value of a bit
    718   // field |T| in |word32|. Returns result as a word-size node.
    719   template <typename T>
    720   compiler::Node* DecodeWordFromWord32(compiler::Node* word32) {
    721     return DecodeWord<T>(ChangeUint32ToWord(word32));
    722   }
    723 
    724   // Decodes an unsigned (!) value from |word32| to an uint32 node.
    725   compiler::Node* DecodeWord32(compiler::Node* word32, uint32_t shift,
    726                                uint32_t mask);
    727 
    728   // Decodes an unsigned (!) value from |word| to a word-size node.
    729   compiler::Node* DecodeWord(compiler::Node* word, uint32_t shift,
    730                              uint32_t mask);
    731 
    732   // Returns true if any of the |T|'s bits in given |word32| are set.
    733   template <typename T>
    734   compiler::Node* IsSetWord32(compiler::Node* word32) {
    735     return IsSetWord32(word32, T::kMask);
    736   }
    737 
    738   // Returns true if any of the mask's bits in given |word32| are set.
    739   compiler::Node* IsSetWord32(compiler::Node* word32, uint32_t mask) {
    740     return Word32NotEqual(Word32And(word32, Int32Constant(mask)),
    741                           Int32Constant(0));
    742   }
    743 
    744   // Returns true if any of the |T|'s bits in given |word| are set.
    745   template <typename T>
    746   compiler::Node* IsSetWord(compiler::Node* word) {
    747     return WordNotEqual(WordAnd(word, IntPtrConstant(T::kMask)),
    748                         IntPtrConstant(0));
    749   }
    750 
    751   void SetCounter(StatsCounter* counter, int value);
    752   void IncrementCounter(StatsCounter* counter, int delta);
    753   void DecrementCounter(StatsCounter* counter, int delta);
    754 
    755   // Generates "if (false) goto label" code. Useful for marking a label as
    756   // "live" to avoid assertion failures during graph building. In the resulting
    757   // code this check will be eliminated.
    758   void Use(Label* label);
    759 
    760   // Various building blocks for stubs doing property lookups.
    761   void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index,
    762                  Label* if_keyisunique, Label* if_bailout);
    763 
    764   // Calculates array index for given dictionary entry and entry field.
    765   // See Dictionary::EntryToIndex().
    766   template <typename Dictionary>
    767   compiler::Node* EntryToIndex(compiler::Node* entry, int field_index);
    768   template <typename Dictionary>
    769   compiler::Node* EntryToIndex(compiler::Node* entry) {
    770     return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
    771   }
    772   // Calculate a valid size for the a hash table.
    773   compiler::Node* HashTableComputeCapacity(compiler::Node* at_least_space_for);
    774 
    775   // Looks up an entry in a NameDictionaryBase successor. If the entry is found
    776   // control goes to {if_found} and {var_name_index} contains an index of the
    777   // key field of the entry found. If the key is not found control goes to
    778   // {if_not_found}.
    779   static const int kInlinedDictionaryProbes = 4;
    780   template <typename Dictionary>
    781   void NameDictionaryLookup(compiler::Node* dictionary,
    782                             compiler::Node* unique_name, Label* if_found,
    783                             Variable* var_name_index, Label* if_not_found,
    784                             int inlined_probes = kInlinedDictionaryProbes);
    785 
    786   compiler::Node* ComputeIntegerHash(compiler::Node* key, compiler::Node* seed);
    787 
    788   template <typename Dictionary>
    789   void NumberDictionaryLookup(compiler::Node* dictionary,
    790                               compiler::Node* intptr_index, Label* if_found,
    791                               Variable* var_entry, Label* if_not_found);
    792 
    793   // Tries to check if {object} has own {unique_name} property.
    794   void TryHasOwnProperty(compiler::Node* object, compiler::Node* map,
    795                          compiler::Node* instance_type,
    796                          compiler::Node* unique_name, Label* if_found,
    797                          Label* if_not_found, Label* if_bailout);
    798 
    799   // Tries to get {object}'s own {unique_name} property value. If the property
    800   // is an accessor then it also calls a getter. If the property is a double
    801   // field it re-wraps value in an immutable heap number.
    802   void TryGetOwnProperty(compiler::Node* context, compiler::Node* receiver,
    803                          compiler::Node* object, compiler::Node* map,
    804                          compiler::Node* instance_type,
    805                          compiler::Node* unique_name, Label* if_found,
    806                          Variable* var_value, Label* if_not_found,
    807                          Label* if_bailout);
    808 
    809   void LoadPropertyFromFastObject(compiler::Node* object, compiler::Node* map,
    810                                   compiler::Node* descriptors,
    811                                   compiler::Node* name_index,
    812                                   Variable* var_details, Variable* var_value);
    813 
    814   void LoadPropertyFromNameDictionary(compiler::Node* dictionary,
    815                                       compiler::Node* entry,
    816                                       Variable* var_details,
    817                                       Variable* var_value);
    818 
    819   void LoadPropertyFromGlobalDictionary(compiler::Node* dictionary,
    820                                         compiler::Node* entry,
    821                                         Variable* var_details,
    822                                         Variable* var_value, Label* if_deleted);
    823 
    824   // Generic property lookup generator. If the {object} is fast and
    825   // {unique_name} property is found then the control goes to {if_found_fast}
    826   // label and {var_meta_storage} and {var_name_index} will contain
    827   // DescriptorArray and an index of the descriptor's name respectively.
    828   // If the {object} is slow or global then the control goes to {if_found_dict}
    829   // or {if_found_global} and the {var_meta_storage} and {var_name_index} will
    830   // contain a dictionary and an index of the key field of the found entry.
    831   // If property is not found or given lookup is not supported then
    832   // the control goes to {if_not_found} or {if_bailout} respectively.
    833   //
    834   // Note: this code does not check if the global dictionary points to deleted
    835   // entry! This has to be done by the caller.
    836   void TryLookupProperty(compiler::Node* object, compiler::Node* map,
    837                          compiler::Node* instance_type,
    838                          compiler::Node* unique_name, Label* if_found_fast,
    839                          Label* if_found_dict, Label* if_found_global,
    840                          Variable* var_meta_storage, Variable* var_name_index,
    841                          Label* if_not_found, Label* if_bailout);
    842 
    843   void TryLookupElement(compiler::Node* object, compiler::Node* map,
    844                         compiler::Node* instance_type,
    845                         compiler::Node* intptr_index, Label* if_found,
    846                         Label* if_not_found, Label* if_bailout);
    847 
    848   // This is a type of a lookup in holder generator function. In case of a
    849   // property lookup the {key} is guaranteed to be a unique name and in case of
    850   // element lookup the key is an Int32 index.
    851   typedef std::function<void(compiler::Node* receiver, compiler::Node* holder,
    852                              compiler::Node* map, compiler::Node* instance_type,
    853                              compiler::Node* key, Label* next_holder,
    854                              Label* if_bailout)>
    855       LookupInHolder;
    856 
    857   // Generic property prototype chain lookup generator.
    858   // For properties it generates lookup using given {lookup_property_in_holder}
    859   // and for elements it uses {lookup_element_in_holder}.
    860   // Upon reaching the end of prototype chain the control goes to {if_end}.
    861   // If it can't handle the case {receiver}/{key} case then the control goes
    862   // to {if_bailout}.
    863   void TryPrototypeChainLookup(compiler::Node* receiver, compiler::Node* key,
    864                                LookupInHolder& lookup_property_in_holder,
    865                                LookupInHolder& lookup_element_in_holder,
    866                                Label* if_end, Label* if_bailout);
    867 
    868   // Instanceof helpers.
    869   // ES6 section 7.3.19 OrdinaryHasInstance (C, O)
    870   compiler::Node* OrdinaryHasInstance(compiler::Node* context,
    871                                       compiler::Node* callable,
    872                                       compiler::Node* object);
    873 
    874   // Load/StoreIC helpers.
    875   struct LoadICParameters {
    876     LoadICParameters(compiler::Node* context, compiler::Node* receiver,
    877                      compiler::Node* name, compiler::Node* slot,
    878                      compiler::Node* vector)
    879         : context(context),
    880           receiver(receiver),
    881           name(name),
    882           slot(slot),
    883           vector(vector) {}
    884 
    885     compiler::Node* context;
    886     compiler::Node* receiver;
    887     compiler::Node* name;
    888     compiler::Node* slot;
    889     compiler::Node* vector;
    890   };
    891 
    892   struct StoreICParameters : public LoadICParameters {
    893     StoreICParameters(compiler::Node* context, compiler::Node* receiver,
    894                       compiler::Node* name, compiler::Node* value,
    895                       compiler::Node* slot, compiler::Node* vector)
    896         : LoadICParameters(context, receiver, name, slot, vector),
    897           value(value) {}
    898     compiler::Node* value;
    899   };
    900 
    901   // Load type feedback vector from the stub caller's frame.
    902   compiler::Node* LoadTypeFeedbackVectorForStub();
    903 
    904   // Update the type feedback vector.
    905   void UpdateFeedback(compiler::Node* feedback,
    906                       compiler::Node* type_feedback_vector,
    907                       compiler::Node* slot_id);
    908 
    909   compiler::Node* LoadReceiverMap(compiler::Node* receiver);
    910 
    911   // Checks monomorphic case. Returns {feedback} entry of the vector.
    912   compiler::Node* TryMonomorphicCase(compiler::Node* slot,
    913                                      compiler::Node* vector,
    914                                      compiler::Node* receiver_map,
    915                                      Label* if_handler, Variable* var_handler,
    916                                      Label* if_miss);
    917   void HandlePolymorphicCase(compiler::Node* receiver_map,
    918                              compiler::Node* feedback, Label* if_handler,
    919                              Variable* var_handler, Label* if_miss,
    920                              int unroll_count);
    921   void HandleKeyedStorePolymorphicCase(compiler::Node* receiver_map,
    922                                        compiler::Node* feedback,
    923                                        Label* if_handler, Variable* var_handler,
    924                                        Label* if_transition_handler,
    925                                        Variable* var_transition_map_cell,
    926                                        Label* if_miss);
    927 
    928   compiler::Node* StubCachePrimaryOffset(compiler::Node* name,
    929                                          compiler::Node* map);
    930 
    931   compiler::Node* StubCacheSecondaryOffset(compiler::Node* name,
    932                                            compiler::Node* seed);
    933 
    934   // This enum is used here as a replacement for StubCache::Table to avoid
    935   // including stub cache header.
    936   enum StubCacheTable : int;
    937 
    938   void TryProbeStubCacheTable(StubCache* stub_cache, StubCacheTable table_id,
    939                               compiler::Node* entry_offset,
    940                               compiler::Node* name, compiler::Node* map,
    941                               Label* if_handler, Variable* var_handler,
    942                               Label* if_miss);
    943 
    944   void TryProbeStubCache(StubCache* stub_cache, compiler::Node* receiver,
    945                          compiler::Node* name, Label* if_handler,
    946                          Variable* var_handler, Label* if_miss);
    947 
    948   // Extends properties backing store by JSObject::kFieldsAdded elements.
    949   void ExtendPropertiesBackingStore(compiler::Node* object);
    950 
    951   compiler::Node* PrepareValueForWrite(compiler::Node* value,
    952                                        Representation representation,
    953                                        Label* bailout);
    954 
    955   void StoreNamedField(compiler::Node* object, FieldIndex index,
    956                        Representation representation, compiler::Node* value,
    957                        bool transition_to_field);
    958 
    959   void StoreNamedField(compiler::Node* object, compiler::Node* offset,
    960                        bool is_inobject, Representation representation,
    961                        compiler::Node* value, bool transition_to_field);
    962 
    963   // Emits keyed sloppy arguments load. Returns either the loaded value.
    964   compiler::Node* LoadKeyedSloppyArguments(compiler::Node* receiver,
    965                                            compiler::Node* key,
    966                                            Label* bailout) {
    967     return EmitKeyedSloppyArguments(receiver, key, nullptr, bailout);
    968   }
    969 
    970   // Emits keyed sloppy arguments store.
    971   void StoreKeyedSloppyArguments(compiler::Node* receiver, compiler::Node* key,
    972                                  compiler::Node* value, Label* bailout) {
    973     DCHECK_NOT_NULL(value);
    974     EmitKeyedSloppyArguments(receiver, key, value, bailout);
    975   }
    976 
    977   // Loads script context from the script context table.
    978   compiler::Node* LoadScriptContext(compiler::Node* context, int context_index);
    979 
    980   compiler::Node* Int32ToUint8Clamped(compiler::Node* int32_value);
    981   compiler::Node* Float64ToUint8Clamped(compiler::Node* float64_value);
    982 
    983   compiler::Node* PrepareValueForWriteToTypedArray(compiler::Node* key,
    984                                                    ElementsKind elements_kind,
    985                                                    Label* bailout);
    986 
    987   // Store value to an elements array with given elements kind.
    988   void StoreElement(compiler::Node* elements, ElementsKind kind,
    989                     compiler::Node* index, compiler::Node* value,
    990                     ParameterMode mode);
    991 
    992   void EmitElementStore(compiler::Node* object, compiler::Node* key,
    993                         compiler::Node* value, bool is_jsarray,
    994                         ElementsKind elements_kind,
    995                         KeyedAccessStoreMode store_mode, Label* bailout);
    996 
    997   compiler::Node* CheckForCapacityGrow(compiler::Node* object,
    998                                        compiler::Node* elements,
    999                                        ElementsKind kind,
   1000                                        compiler::Node* length,
   1001                                        compiler::Node* key, ParameterMode mode,
   1002                                        bool is_js_array, Label* bailout);
   1003 
   1004   compiler::Node* CopyElementsOnWrite(compiler::Node* object,
   1005                                       compiler::Node* elements,
   1006                                       ElementsKind kind, compiler::Node* length,
   1007                                       ParameterMode mode, Label* bailout);
   1008 
   1009   void LoadIC(const LoadICParameters* p);
   1010   void LoadICProtoArray(const LoadICParameters* p, compiler::Node* handler);
   1011   void LoadGlobalIC(const LoadICParameters* p);
   1012   void KeyedLoadIC(const LoadICParameters* p);
   1013   void KeyedLoadICGeneric(const LoadICParameters* p);
   1014   void StoreIC(const StoreICParameters* p);
   1015   void KeyedStoreIC(const StoreICParameters* p, LanguageMode language_mode);
   1016 
   1017   void TransitionElementsKind(compiler::Node* object, compiler::Node* map,
   1018                               ElementsKind from_kind, ElementsKind to_kind,
   1019                               bool is_jsarray, Label* bailout);
   1020 
   1021   void TrapAllocationMemento(compiler::Node* object, Label* memento_found);
   1022 
   1023   compiler::Node* PageFromAddress(compiler::Node* address);
   1024 
   1025   // Get the enumerable length from |map| and return the result as a Smi.
   1026   compiler::Node* EnumLength(compiler::Node* map);
   1027 
   1028   // Check the cache validity for |receiver|. Branch to |use_cache| if
   1029   // the cache is valid, otherwise branch to |use_runtime|.
   1030   void CheckEnumCache(compiler::Node* receiver,
   1031                       CodeStubAssembler::Label* use_cache,
   1032                       CodeStubAssembler::Label* use_runtime);
   1033 
   1034   // Create a new weak cell with a specified value and install it into a
   1035   // feedback vector.
   1036   compiler::Node* CreateWeakCellInFeedbackVector(
   1037       compiler::Node* feedback_vector, compiler::Node* slot,
   1038       compiler::Node* value);
   1039 
   1040   // Create a new AllocationSite and install it into a feedback vector.
   1041   compiler::Node* CreateAllocationSiteInFeedbackVector(
   1042       compiler::Node* feedback_vector, compiler::Node* slot);
   1043 
   1044   enum class IndexAdvanceMode { kPre, kPost };
   1045 
   1046   void BuildFastLoop(
   1047       const VariableList& var_list, MachineRepresentation index_rep,
   1048       compiler::Node* start_index, compiler::Node* end_index,
   1049       std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
   1050           body,
   1051       int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre);
   1052 
   1053   void BuildFastLoop(
   1054       MachineRepresentation index_rep, compiler::Node* start_index,
   1055       compiler::Node* end_index,
   1056       std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
   1057           body,
   1058       int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre) {
   1059     BuildFastLoop(VariableList(0, zone()), index_rep, start_index, end_index,
   1060                   body, increment, mode);
   1061   }
   1062 
   1063   enum class ForEachDirection { kForward, kReverse };
   1064 
   1065   void BuildFastFixedArrayForEach(
   1066       compiler::Node* fixed_array, ElementsKind kind,
   1067       compiler::Node* first_element_inclusive,
   1068       compiler::Node* last_element_exclusive,
   1069       std::function<void(CodeStubAssembler* assembler,
   1070                          compiler::Node* fixed_array, compiler::Node* offset)>
   1071           body,
   1072       ParameterMode mode = INTPTR_PARAMETERS,
   1073       ForEachDirection direction = ForEachDirection::kReverse);
   1074 
   1075   compiler::Node* GetArrayAllocationSize(compiler::Node* element_count,
   1076                                          ElementsKind kind, ParameterMode mode,
   1077                                          int header_size) {
   1078     return ElementOffsetFromIndex(element_count, kind, mode, header_size);
   1079   }
   1080 
   1081   compiler::Node* GetFixedArrayAllocationSize(compiler::Node* element_count,
   1082                                               ElementsKind kind,
   1083                                               ParameterMode mode) {
   1084     return GetArrayAllocationSize(element_count, kind, mode,
   1085                                   FixedArray::kHeaderSize);
   1086   }
   1087 
   1088   enum RelationalComparisonMode {
   1089     kLessThan,
   1090     kLessThanOrEqual,
   1091     kGreaterThan,
   1092     kGreaterThanOrEqual
   1093   };
   1094 
   1095   compiler::Node* RelationalComparison(RelationalComparisonMode mode,
   1096                                        compiler::Node* lhs, compiler::Node* rhs,
   1097                                        compiler::Node* context);
   1098 
   1099   void BranchIfNumericRelationalComparison(RelationalComparisonMode mode,
   1100                                            compiler::Node* lhs,
   1101                                            compiler::Node* rhs, Label* if_true,
   1102                                            Label* if_false);
   1103 
   1104   void GotoUnlessNumberLessThan(compiler::Node* lhs, compiler::Node* rhs,
   1105                                 Label* if_false);
   1106 
   1107   enum ResultMode { kDontNegateResult, kNegateResult };
   1108 
   1109   compiler::Node* Equal(ResultMode mode, compiler::Node* lhs,
   1110                         compiler::Node* rhs, compiler::Node* context);
   1111 
   1112   compiler::Node* StrictEqual(ResultMode mode, compiler::Node* lhs,
   1113                               compiler::Node* rhs, compiler::Node* context);
   1114 
   1115   // ECMA#sec-samevalue
   1116   // Similar to StrictEqual except that NaNs are treated as equal and minus zero
   1117   // differs from positive zero.
   1118   // Unlike Equal and StrictEqual, returns a value suitable for use in Branch
   1119   // instructions, e.g. Branch(SameValue(...), &label).
   1120   compiler::Node* SameValue(compiler::Node* lhs, compiler::Node* rhs,
   1121                             compiler::Node* context);
   1122 
   1123   compiler::Node* HasProperty(
   1124       compiler::Node* object, compiler::Node* key, compiler::Node* context,
   1125       Runtime::FunctionId fallback_runtime_function_id = Runtime::kHasProperty);
   1126   compiler::Node* ForInFilter(compiler::Node* key, compiler::Node* object,
   1127                               compiler::Node* context);
   1128 
   1129   compiler::Node* Typeof(compiler::Node* value, compiler::Node* context);
   1130 
   1131   compiler::Node* InstanceOf(compiler::Node* object, compiler::Node* callable,
   1132                              compiler::Node* context);
   1133 
   1134   // TypedArray/ArrayBuffer helpers
   1135   compiler::Node* IsDetachedBuffer(compiler::Node* buffer);
   1136 
   1137   compiler::Node* ElementOffsetFromIndex(compiler::Node* index,
   1138                                          ElementsKind kind, ParameterMode mode,
   1139                                          int base_size = 0);
   1140 
   1141  protected:
   1142   void HandleStoreICHandlerCase(const StoreICParameters* p,
   1143                                 compiler::Node* handler, Label* miss);
   1144 
   1145  private:
   1146   friend class CodeStubArguments;
   1147 
   1148   enum ElementSupport { kOnlyProperties, kSupportElements };
   1149 
   1150   void DescriptorLookupLinear(compiler::Node* unique_name,
   1151                               compiler::Node* descriptors, compiler::Node* nof,
   1152                               Label* if_found, Variable* var_name_index,
   1153                               Label* if_not_found);
   1154   compiler::Node* CallGetterIfAccessor(compiler::Node* value,
   1155                                        compiler::Node* details,
   1156                                        compiler::Node* context,
   1157                                        compiler::Node* receiver,
   1158                                        Label* if_bailout);
   1159 
   1160   void HandleLoadICHandlerCase(
   1161       const LoadICParameters* p, compiler::Node* handler, Label* miss,
   1162       ElementSupport support_elements = kOnlyProperties);
   1163 
   1164   void HandleLoadICSmiHandlerCase(const LoadICParameters* p,
   1165                                   compiler::Node* holder,
   1166                                   compiler::Node* smi_handler, Label* miss,
   1167                                   ElementSupport support_elements);
   1168 
   1169   void HandleLoadICProtoHandler(const LoadICParameters* p,
   1170                                 compiler::Node* handler, Variable* var_holder,
   1171                                 Variable* var_smi_handler,
   1172                                 Label* if_smi_handler, Label* miss);
   1173 
   1174   compiler::Node* EmitLoadICProtoArrayCheck(const LoadICParameters* p,
   1175                                             compiler::Node* handler,
   1176                                             compiler::Node* handler_length,
   1177                                             compiler::Node* handler_flags,
   1178                                             Label* miss);
   1179 
   1180   void CheckPrototype(compiler::Node* prototype_cell, compiler::Node* name,
   1181                       Label* miss);
   1182 
   1183   void NameDictionaryNegativeLookup(compiler::Node* object,
   1184                                     compiler::Node* name, Label* miss);
   1185 
   1186   // If |transition| is nullptr then the normal field store is generated or
   1187   // transitioning store otherwise.
   1188   void HandleStoreFieldAndReturn(compiler::Node* handler_word,
   1189                                  compiler::Node* holder,
   1190                                  Representation representation,
   1191                                  compiler::Node* value,
   1192                                  compiler::Node* transition, Label* miss);
   1193 
   1194   // If |transition| is nullptr then the normal field store is generated or
   1195   // transitioning store otherwise.
   1196   void HandleStoreICSmiHandlerCase(compiler::Node* handler_word,
   1197                                    compiler::Node* holder,
   1198                                    compiler::Node* value,
   1199                                    compiler::Node* transition, Label* miss);
   1200 
   1201   void HandleStoreICProtoHandler(const StoreICParameters* p,
   1202                                  compiler::Node* handler, Label* miss);
   1203 
   1204   compiler::Node* TryToIntptr(compiler::Node* key, Label* miss);
   1205   void EmitFastElementsBoundsCheck(compiler::Node* object,
   1206                                    compiler::Node* elements,
   1207                                    compiler::Node* intptr_index,
   1208                                    compiler::Node* is_jsarray_condition,
   1209                                    Label* miss);
   1210   void EmitElementLoad(compiler::Node* object, compiler::Node* elements,
   1211                        compiler::Node* elements_kind, compiler::Node* key,
   1212                        compiler::Node* is_jsarray_condition, Label* if_hole,
   1213                        Label* rebox_double, Variable* var_double_value,
   1214                        Label* unimplemented_elements_kind, Label* out_of_bounds,
   1215                        Label* miss);
   1216   void BranchIfPrototypesHaveNoElements(compiler::Node* receiver_map,
   1217                                         Label* definitely_no_elements,
   1218                                         Label* possibly_elements);
   1219 
   1220   compiler::Node* AllocateRawAligned(compiler::Node* size_in_bytes,
   1221                                      AllocationFlags flags,
   1222                                      compiler::Node* top_address,
   1223                                      compiler::Node* limit_address);
   1224   compiler::Node* AllocateRawUnaligned(compiler::Node* size_in_bytes,
   1225                                        AllocationFlags flags,
   1226                                        compiler::Node* top_adddress,
   1227                                        compiler::Node* limit_address);
   1228   // Allocate and return a JSArray of given total size in bytes with header
   1229   // fields initialized.
   1230   compiler::Node* AllocateUninitializedJSArray(ElementsKind kind,
   1231                                                compiler::Node* array_map,
   1232                                                compiler::Node* length,
   1233                                                compiler::Node* allocation_site,
   1234                                                compiler::Node* size_in_bytes);
   1235 
   1236   compiler::Node* SmiShiftBitsConstant();
   1237 
   1238   // Emits keyed sloppy arguments load if the |value| is nullptr or store
   1239   // otherwise. Returns either the loaded value or |value|.
   1240   compiler::Node* EmitKeyedSloppyArguments(compiler::Node* receiver,
   1241                                            compiler::Node* key,
   1242                                            compiler::Node* value,
   1243                                            Label* bailout);
   1244 
   1245   compiler::Node* AllocateSlicedString(Heap::RootListIndex map_root_index,
   1246                                        compiler::Node* length,
   1247                                        compiler::Node* parent,
   1248                                        compiler::Node* offset);
   1249 
   1250   compiler::Node* AllocateConsString(Heap::RootListIndex map_root_index,
   1251                                      compiler::Node* length,
   1252                                      compiler::Node* first,
   1253                                      compiler::Node* second,
   1254                                      AllocationFlags flags);
   1255 
   1256   static const int kElementLoopUnrollThreshold = 8;
   1257 };
   1258 
   1259 class CodeStubArguments {
   1260  public:
   1261   // |argc| specifies the number of arguments passed to the builtin excluding
   1262   // the receiver.
   1263   CodeStubArguments(CodeStubAssembler* assembler, compiler::Node* argc,
   1264                     CodeStubAssembler::ParameterMode mode =
   1265                         CodeStubAssembler::INTPTR_PARAMETERS);
   1266 
   1267   compiler::Node* GetReceiver();
   1268 
   1269   // |index| is zero-based and does not include the receiver
   1270   compiler::Node* AtIndex(compiler::Node* index,
   1271                           CodeStubAssembler::ParameterMode mode =
   1272                               CodeStubAssembler::INTPTR_PARAMETERS);
   1273 
   1274   compiler::Node* AtIndex(int index);
   1275 
   1276   typedef std::function<void(CodeStubAssembler* assembler, compiler::Node* arg)>
   1277       ForEachBodyFunction;
   1278 
   1279   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
   1280   void ForEach(ForEachBodyFunction body, compiler::Node* first = nullptr,
   1281                compiler::Node* last = nullptr,
   1282                CodeStubAssembler::ParameterMode mode =
   1283                    CodeStubAssembler::INTPTR_PARAMETERS) {
   1284     CodeStubAssembler::VariableList list(0, assembler_->zone());
   1285     ForEach(list, body, first, last);
   1286   }
   1287 
   1288   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
   1289   void ForEach(const CodeStubAssembler::VariableList& vars,
   1290                ForEachBodyFunction body, compiler::Node* first = nullptr,
   1291                compiler::Node* last = nullptr,
   1292                CodeStubAssembler::ParameterMode mode =
   1293                    CodeStubAssembler::INTPTR_PARAMETERS);
   1294 
   1295   void PopAndReturn(compiler::Node* value);
   1296 
   1297  private:
   1298   compiler::Node* GetArguments();
   1299 
   1300   CodeStubAssembler* assembler_;
   1301   compiler::Node* argc_;
   1302   compiler::Node* arguments_;
   1303   compiler::Node* fp_;
   1304 };
   1305 
   1306 #ifdef DEBUG
   1307 #define CSA_ASSERT(csa, x) \
   1308   (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__)
   1309 #else
   1310 #define CSA_ASSERT(csa, x) ((void)0)
   1311 #endif
   1312 
   1313 #ifdef ENABLE_SLOW_DCHECKS
   1314 #define CSA_SLOW_ASSERT(csa, x)                                 \
   1315   if (FLAG_enable_slow_asserts) {                               \
   1316     (csa)->Assert([&] { return (x); }, #x, __FILE__, __LINE__); \
   1317   }
   1318 #else
   1319 #define CSA_SLOW_ASSERT(csa, x) ((void)0)
   1320 #endif
   1321 
   1322 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
   1323 
   1324 }  // namespace internal
   1325 }  // namespace v8
   1326 #endif  // V8_CODE_STUB_ASSEMBLER_H_
   1327