code-stub-assembler.h revision c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7a
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
14namespace v8 {
15namespace internal {
16
17class CallInterfaceDescriptor;
18class StatsCounter;
19class StubCache;
20
21enum 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).
45class 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
1259class 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
1322DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
1323
1324}  // namespace internal
1325}  // namespace v8
1326#endif  // V8_CODE_STUB_ASSEMBLER_H_
1327