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.
OptimalParameterMode()77   ParameterMode OptimalParameterMode() const {
78     return Is64() ? INTPTR_PARAMETERS : SMI_PARAMETERS;
79   }
80 
UntagParameter(compiler::Node * value,ParameterMode mode)81   compiler::Node* UntagParameter(compiler::Node* value, ParameterMode mode) {
82     if (mode != SMI_PARAMETERS) value = SmiUntag(value);
83     return value;
84   }
85 
TagParameter(compiler::Node * value,ParameterMode mode)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);
SmiFromWord(compiler::Node * value)128   compiler::Node* SmiFromWord(compiler::Node* value) { return SmiTag(value); }
129   compiler::Node* SmiFromWord32(compiler::Node* value);
SmiToWord(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);
SmiOr(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 
BranchIfSmiEqual(compiler::Node * a,compiler::Node * b,Label * if_true,Label * if_false)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 
BranchIfSmiLessThan(compiler::Node * a,compiler::Node * b,Label * if_true,Label * if_false)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 
BranchIfSmiLessThanOrEqual(compiler::Node * a,compiler::Node * b,Label * if_true,Label * if_false)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 
BranchIfFloat64IsNaN(compiler::Node * value,Label * if_true,Label * if_false)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);
BranchIfSimd128Equal(compiler::Node * lhs,compiler::Node * rhs,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>
DecodeWord32(compiler::Node * word32)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>
DecodeWord(compiler::Node * word)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>
DecodeWordFromWord32(compiler::Node * word32)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>
IsSetWord32(compiler::Node * word32)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.
IsSetWord32(compiler::Node * word32,uint32_t mask)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>
IsSetWord(compiler::Node * word)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>
EntryToIndex(compiler::Node * entry)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 {
LoadICParametersLoadICParameters876     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 {
StoreICParametersStoreICParameters893     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.
LoadKeyedSloppyArguments(compiler::Node * receiver,compiler::Node * key,Label * bailout)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.
StoreKeyedSloppyArguments(compiler::Node * receiver,compiler::Node * key,compiler::Node * value,Label * bailout)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 
GetArrayAllocationSize(compiler::Node * element_count,ElementsKind kind,ParameterMode mode,int header_size)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 
GetFixedArrayAllocationSize(compiler::Node * element_count,ElementsKind kind,ParameterMode mode)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