• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_COMPILER_CODE_ASSEMBLER_H_
6 #define V8_COMPILER_CODE_ASSEMBLER_H_
7 
8 #include <initializer_list>
9 #include <map>
10 #include <memory>
11 #include <sstream>
12 
13 // Clients of this interface shouldn't depend on lots of compiler internals.
14 // Do not include anything from src/compiler here!
15 #include "include/cppgc/source-location.h"
16 #include "src/base/macros.h"
17 #include "src/base/type-traits.h"
18 #include "src/builtins/builtins.h"
19 #include "src/codegen/code-factory.h"
20 #include "src/codegen/machine-type.h"
21 #include "src/codegen/source-position.h"
22 #include "src/codegen/tnode.h"
23 #include "src/heap/heap.h"
24 #include "src/objects/arguments.h"
25 #include "src/objects/data-handler.h"
26 #include "src/objects/heap-number.h"
27 #include "src/objects/js-array-buffer.h"
28 #include "src/objects/js-collection.h"
29 #include "src/objects/js-proxy.h"
30 #include "src/objects/map.h"
31 #include "src/objects/maybe-object.h"
32 #include "src/objects/objects.h"
33 #include "src/objects/oddball.h"
34 #include "src/objects/smi.h"
35 #include "src/objects/tagged-index.h"
36 #include "src/runtime/runtime.h"
37 #include "src/utils/allocation.h"
38 #include "src/zone/zone-containers.h"
39 
40 namespace v8 {
41 namespace internal {
42 
43 // Forward declarations.
44 class AsmWasmData;
45 class AsyncGeneratorRequest;
46 struct AssemblerOptions;
47 class BigInt;
48 class CallInterfaceDescriptor;
49 class Callable;
50 class Factory;
51 class InterpreterData;
52 class Isolate;
53 class JSAsyncFunctionObject;
54 class JSAsyncGeneratorObject;
55 class JSCollator;
56 class JSCollection;
57 class JSDateTimeFormat;
58 class JSDisplayNames;
59 class JSListFormat;
60 class JSLocale;
61 class JSNumberFormat;
62 class JSPluralRules;
63 class JSRegExpStringIterator;
64 class JSRelativeTimeFormat;
65 class JSSegmentIterator;
66 class JSSegmenter;
67 class JSSegments;
68 class JSV8BreakIterator;
69 class JSWeakCollection;
70 class JSFinalizationRegistry;
71 class JSWeakMap;
72 class JSWeakRef;
73 class JSWeakSet;
74 class ProfileDataFromFile;
75 class PromiseCapability;
76 class PromiseFulfillReactionJobTask;
77 class PromiseReaction;
78 class PromiseReactionJobTask;
79 class PromiseRejectReactionJobTask;
80 class Zone;
81 #define MAKE_FORWARD_DECLARATION(Name) class Name;
82 TORQUE_DEFINED_CLASS_LIST(MAKE_FORWARD_DECLARATION)
83 #undef MAKE_FORWARD_DECLARATION
84 
85 template <typename T>
86 class Signature;
87 
88 #define ENUM_ELEMENT(Name) k##Name,
89 #define ENUM_STRUCT_ELEMENT(NAME, Name, name) k##Name,
90 enum class ObjectType {
91   ENUM_ELEMENT(Object)                 //
92   ENUM_ELEMENT(Smi)                    //
93   ENUM_ELEMENT(TaggedIndex)            //
94   ENUM_ELEMENT(HeapObject)             //
95   OBJECT_TYPE_LIST(ENUM_ELEMENT)       //
96   HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT)  //
97   STRUCT_LIST(ENUM_STRUCT_ELEMENT)     //
98 };
99 #undef ENUM_ELEMENT
100 #undef ENUM_STRUCT_ELEMENT
101 
102 enum class CheckBounds { kAlways, kDebugOnly };
NeedsBoundsCheck(CheckBounds check_bounds)103 inline bool NeedsBoundsCheck(CheckBounds check_bounds) {
104   switch (check_bounds) {
105     case CheckBounds::kAlways:
106       return true;
107     case CheckBounds::kDebugOnly:
108       return DEBUG_BOOL;
109   }
110 }
111 
112 enum class StoreToObjectWriteBarrier { kNone, kMap, kFull };
113 
114 class AccessCheckNeeded;
115 class BigIntBase;
116 class BigIntWrapper;
117 class ClassBoilerplate;
118 class BooleanWrapper;
119 class CompilationCacheTable;
120 class Constructor;
121 class Filler;
122 class FunctionTemplateRareData;
123 class HeapNumber;
124 class InternalizedString;
125 class JSArgumentsObject;
126 class JSArrayBufferView;
127 class JSContextExtensionObject;
128 class JSError;
129 class JSSloppyArgumentsObject;
130 class MapCache;
131 class NativeContext;
132 class NumberWrapper;
133 class ScriptWrapper;
134 class SloppyArgumentsElements;
135 class StringWrapper;
136 class SymbolWrapper;
137 class Undetectable;
138 class UniqueName;
139 class WasmCapiFunctionData;
140 class WasmExceptionObject;
141 class WasmExceptionPackage;
142 class WasmExceptionTag;
143 class WasmExportedFunctionData;
144 class WasmGlobalObject;
145 class WasmIndirectFunctionTable;
146 class WasmJSFunctionData;
147 class WasmMemoryObject;
148 class WasmModuleObject;
149 class WasmTableObject;
150 
151 template <class T>
152 struct ObjectTypeOf {};
153 
154 #define OBJECT_TYPE_CASE(Name)                           \
155   template <>                                            \
156   struct ObjectTypeOf<Name> {                            \
157     static const ObjectType value = ObjectType::k##Name; \
158   };
159 #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)        \
160   template <>                                            \
161   struct ObjectTypeOf<Name> {                            \
162     static const ObjectType value = ObjectType::k##Name; \
163   };
164 #define OBJECT_TYPE_TEMPLATE_CASE(Name)                  \
165   template <class... Args>                               \
166   struct ObjectTypeOf<Name<Args...>> {                   \
167     static const ObjectType value = ObjectType::k##Name; \
168   };
169 OBJECT_TYPE_CASE(Object)
170 OBJECT_TYPE_CASE(Smi)
171 OBJECT_TYPE_CASE(TaggedIndex)
172 OBJECT_TYPE_CASE(HeapObject)
173 OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
174 HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
175 STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
176 HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
177 #undef OBJECT_TYPE_CASE
178 #undef OBJECT_TYPE_STRUCT_CASE
179 #undef OBJECT_TYPE_TEMPLATE_CASE
180 
181 // {raw_value} must be a tagged Object.
182 // {raw_type} must be a tagged Smi.
183 // {raw_location} must be a tagged String.
184 // Returns a tagged Smi.
185 Address CheckObjectType(Address raw_value, Address raw_type,
186                         Address raw_location);
187 
188 namespace compiler {
189 
190 class CallDescriptor;
191 class CodeAssemblerLabel;
192 class CodeAssemblerVariable;
193 template <class T>
194 class TypedCodeAssemblerVariable;
195 class CodeAssemblerState;
196 class JSGraph;
197 class Node;
198 class RawMachineAssembler;
199 class RawMachineLabel;
200 class SourcePositionTable;
201 
202 using CodeAssemblerVariableList = ZoneVector<CodeAssemblerVariable*>;
203 
204 using CodeAssemblerCallback = std::function<void()>;
205 
206 template <class... Types>
207 class CodeAssemblerParameterizedLabel;
208 
209 // This macro alias allows to use PairT<T1, T2> as a macro argument.
210 #define PAIR_TYPE(T1, T2) PairT<T1, T2>
211 
212 #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)          \
213   V(Float32Equal, BoolT, Float32T, Float32T)              \
214   V(Float32LessThan, BoolT, Float32T, Float32T)           \
215   V(Float32LessThanOrEqual, BoolT, Float32T, Float32T)    \
216   V(Float32GreaterThan, BoolT, Float32T, Float32T)        \
217   V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
218   V(Float64Equal, BoolT, Float64T, Float64T)              \
219   V(Float64NotEqual, BoolT, Float64T, Float64T)           \
220   V(Float64LessThan, BoolT, Float64T, Float64T)           \
221   V(Float64LessThanOrEqual, BoolT, Float64T, Float64T)    \
222   V(Float64GreaterThan, BoolT, Float64T, Float64T)        \
223   V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
224   /* Use Word32Equal if you need Int32Equal */            \
225   V(Int32GreaterThan, BoolT, Word32T, Word32T)            \
226   V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T)     \
227   V(Int32LessThan, BoolT, Word32T, Word32T)               \
228   V(Int32LessThanOrEqual, BoolT, Word32T, Word32T)        \
229   /* Use WordEqual if you need IntPtrEqual */             \
230   V(IntPtrLessThan, BoolT, WordT, WordT)                  \
231   V(IntPtrLessThanOrEqual, BoolT, WordT, WordT)           \
232   V(IntPtrGreaterThan, BoolT, WordT, WordT)               \
233   V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT)        \
234   /* Use Word32Equal if you need Uint32Equal */           \
235   V(Uint32LessThan, BoolT, Word32T, Word32T)              \
236   V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T)       \
237   V(Uint32GreaterThan, BoolT, Word32T, Word32T)           \
238   V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T)    \
239   /* Use WordEqual if you need UintPtrEqual */            \
240   V(UintPtrLessThan, BoolT, WordT, WordT)                 \
241   V(UintPtrLessThanOrEqual, BoolT, WordT, WordT)          \
242   V(UintPtrGreaterThan, BoolT, WordT, WordT)              \
243   V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)
244 
245 #define CODE_ASSEMBLER_BINARY_OP_LIST(V)                                \
246   CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V)                              \
247   V(Float64Add, Float64T, Float64T, Float64T)                           \
248   V(Float64Sub, Float64T, Float64T, Float64T)                           \
249   V(Float64Mul, Float64T, Float64T, Float64T)                           \
250   V(Float64Div, Float64T, Float64T, Float64T)                           \
251   V(Float64Mod, Float64T, Float64T, Float64T)                           \
252   V(Float64Atan2, Float64T, Float64T, Float64T)                         \
253   V(Float64Pow, Float64T, Float64T, Float64T)                           \
254   V(Float64Max, Float64T, Float64T, Float64T)                           \
255   V(Float64Min, Float64T, Float64T, Float64T)                           \
256   V(Float64InsertLowWord32, Float64T, Float64T, Word32T)                \
257   V(Float64InsertHighWord32, Float64T, Float64T, Word32T)               \
258   V(IntPtrAdd, WordT, WordT, WordT)                                     \
259   V(IntPtrSub, WordT, WordT, WordT)                                     \
260   V(IntPtrMul, WordT, WordT, WordT)                                     \
261   V(IntPtrDiv, IntPtrT, IntPtrT, IntPtrT)                               \
262   V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
263   V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
264   V(Int32Add, Word32T, Word32T, Word32T)                                \
265   V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
266   V(Int32Sub, Word32T, Word32T, Word32T)                                \
267   V(Int32SubWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
268   V(Int32Mul, Word32T, Word32T, Word32T)                                \
269   V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T)     \
270   V(Int32Div, Int32T, Int32T, Int32T)                                   \
271   V(Int32Mod, Int32T, Int32T, Int32T)                                   \
272   V(WordOr, WordT, WordT, WordT)                                        \
273   V(WordAnd, WordT, WordT, WordT)                                       \
274   V(WordXor, WordT, WordT, WordT)                                       \
275   V(WordRor, WordT, WordT, IntegralT)                                   \
276   V(WordShl, WordT, WordT, IntegralT)                                   \
277   V(WordShr, WordT, WordT, IntegralT)                                   \
278   V(WordSar, WordT, WordT, IntegralT)                                   \
279   V(WordSarShiftOutZeros, WordT, WordT, IntegralT)                      \
280   V(Word32Or, Word32T, Word32T, Word32T)                                \
281   V(Word32And, Word32T, Word32T, Word32T)                               \
282   V(Word32Xor, Word32T, Word32T, Word32T)                               \
283   V(Word32Ror, Word32T, Word32T, Word32T)                               \
284   V(Word32Shl, Word32T, Word32T, Word32T)                               \
285   V(Word32Shr, Word32T, Word32T, Word32T)                               \
286   V(Word32Sar, Word32T, Word32T, Word32T)                               \
287   V(Word32SarShiftOutZeros, Word32T, Word32T, Word32T)                  \
288   V(Word64And, Word64T, Word64T, Word64T)                               \
289   V(Word64Or, Word64T, Word64T, Word64T)                                \
290   V(Word64Xor, Word64T, Word64T, Word64T)                               \
291   V(Word64Ror, Word64T, Word64T, Word64T)                               \
292   V(Word64Shl, Word64T, Word64T, Word64T)                               \
293   V(Word64Shr, Word64T, Word64T, Word64T)                               \
294   V(Word64Sar, Word64T, Word64T, Word64T)
295 
296 TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
297 
298 #define CODE_ASSEMBLER_UNARY_OP_LIST(V)                        \
299   V(Float64Abs, Float64T, Float64T)                            \
300   V(Float64Acos, Float64T, Float64T)                           \
301   V(Float64Acosh, Float64T, Float64T)                          \
302   V(Float64Asin, Float64T, Float64T)                           \
303   V(Float64Asinh, Float64T, Float64T)                          \
304   V(Float64Atan, Float64T, Float64T)                           \
305   V(Float64Atanh, Float64T, Float64T)                          \
306   V(Float64Cos, Float64T, Float64T)                            \
307   V(Float64Cosh, Float64T, Float64T)                           \
308   V(Float64Exp, Float64T, Float64T)                            \
309   V(Float64Expm1, Float64T, Float64T)                          \
310   V(Float64Log, Float64T, Float64T)                            \
311   V(Float64Log1p, Float64T, Float64T)                          \
312   V(Float64Log2, Float64T, Float64T)                           \
313   V(Float64Log10, Float64T, Float64T)                          \
314   V(Float64Cbrt, Float64T, Float64T)                           \
315   V(Float64Neg, Float64T, Float64T)                            \
316   V(Float64Sin, Float64T, Float64T)                            \
317   V(Float64Sinh, Float64T, Float64T)                           \
318   V(Float64Sqrt, Float64T, Float64T)                           \
319   V(Float64Tan, Float64T, Float64T)                            \
320   V(Float64Tanh, Float64T, Float64T)                           \
321   V(Float64ExtractLowWord32, Uint32T, Float64T)                \
322   V(Float64ExtractHighWord32, Uint32T, Float64T)               \
323   V(BitcastTaggedToWord, IntPtrT, Object)                      \
324   V(BitcastTaggedToWordForTagAndSmiBits, IntPtrT, AnyTaggedT)  \
325   V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject)            \
326   V(BitcastWordToTagged, Object, WordT)                        \
327   V(BitcastWordToTaggedSigned, Smi, WordT)                     \
328   V(TruncateFloat64ToFloat32, Float32T, Float64T)              \
329   V(TruncateFloat64ToWord32, Uint32T, Float64T)                \
330   V(TruncateInt64ToInt32, Int32T, Int64T)                      \
331   V(ChangeFloat32ToFloat64, Float64T, Float32T)                \
332   V(ChangeFloat64ToUint32, Uint32T, Float64T)                  \
333   V(ChangeFloat64ToUint64, Uint64T, Float64T)                  \
334   V(ChangeInt32ToFloat64, Float64T, Int32T)                    \
335   V(ChangeInt32ToInt64, Int64T, Int32T)                        \
336   V(ChangeUint32ToFloat64, Float64T, Word32T)                  \
337   V(ChangeUint32ToUint64, Uint64T, Word32T)                    \
338   V(BitcastInt32ToFloat32, Float32T, Word32T)                  \
339   V(BitcastFloat32ToInt32, Uint32T, Float32T)                  \
340   V(RoundFloat64ToInt32, Int32T, Float64T)                     \
341   V(RoundInt32ToFloat32, Float32T, Int32T)                     \
342   V(Float64SilenceNaN, Float64T, Float64T)                     \
343   V(Float64RoundDown, Float64T, Float64T)                      \
344   V(Float64RoundUp, Float64T, Float64T)                        \
345   V(Float64RoundTiesEven, Float64T, Float64T)                  \
346   V(Float64RoundTruncate, Float64T, Float64T)                  \
347   V(Word32Clz, Int32T, Word32T)                                \
348   V(Word32BitwiseNot, Word32T, Word32T)                        \
349   V(WordNot, WordT, WordT)                                     \
350   V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T)    \
351   V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T)    \
352   V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
353   V(Word32BinaryNot, BoolT, Word32T)                           \
354   V(StackPointerGreaterThan, BoolT, WordT)
355 
356 // A "public" interface used by components outside of compiler directory to
357 // create code objects with TurboFan's backend. This class is mostly a thin
358 // shim around the RawMachineAssembler, and its primary job is to ensure that
359 // the innards of the RawMachineAssembler and other compiler implementation
360 // details don't leak outside of the the compiler directory..
361 //
362 // V8 components that need to generate low-level code using this interface
363 // should include this header--and this header only--from the compiler
364 // directory (this is actually enforced). Since all interesting data
365 // structures are forward declared, it's not possible for clients to peek
366 // inside the compiler internals.
367 //
368 // In addition to providing isolation between TurboFan and code generation
369 // clients, CodeAssembler also provides an abstraction for creating variables
370 // and enhanced Label functionality to merge variable values along paths where
371 // they have differing values, including loops.
372 //
373 // The CodeAssembler itself is stateless (and instances are expected to be
374 // temporary-scoped and short-lived); all its state is encapsulated into
375 // a CodeAssemblerState instance.
376 class V8_EXPORT_PRIVATE CodeAssembler {
377  public:
CodeAssembler(CodeAssemblerState * state)378   explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
379   ~CodeAssembler();
380 
381   CodeAssembler(const CodeAssembler&) = delete;
382   CodeAssembler& operator=(const CodeAssembler&) = delete;
383 
384   static Handle<Code> GenerateCode(CodeAssemblerState* state,
385                                    const AssemblerOptions& options,
386                                    const ProfileDataFromFile* profile_data);
387   bool Is64() const;
388   bool Is32() const;
389   bool IsFloat64RoundUpSupported() const;
390   bool IsFloat64RoundDownSupported() const;
391   bool IsFloat64RoundTiesEvenSupported() const;
392   bool IsFloat64RoundTruncateSupported() const;
393   bool IsInt32AbsWithOverflowSupported() const;
394   bool IsInt64AbsWithOverflowSupported() const;
395   bool IsIntPtrAbsWithOverflowSupported() const;
396 
397   // Shortened aliases for use in CodeAssembler subclasses.
398   using Label = CodeAssemblerLabel;
399   template <class T>
400   using TVariable = TypedCodeAssemblerVariable<T>;
401   using VariableList = CodeAssemblerVariableList;
402 
403   // ===========================================================================
404   // Base Assembler
405   // ===========================================================================
406 
407   template <class PreviousType, bool FromTyped>
408   class CheckedNode {
409    public:
410 #ifdef DEBUG
CheckedNode(Node * node,CodeAssembler * code_assembler,const char * location)411     CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
412         : node_(node), code_assembler_(code_assembler), location_(location) {}
413 #else
414     CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
415         : node_(node) {}
416 #endif
417 
418     template <class A>
419     operator TNode<A>() {
420       static_assert(
421           !std::is_same<A, MaybeObject>::value,
422           "Can't cast to MaybeObject, use explicit conversion functions. ");
423 
424       static_assert(types_have_common_values<A, PreviousType>::value,
425                     "Incompatible types: this cast can never succeed.");
426       static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
427                     "Coercion to untagged values cannot be "
428                     "checked.");
429       static_assert(
430           !FromTyped ||
431               !std::is_convertible<TNode<PreviousType>, TNode<A>>::value,
432           "Unnecessary CAST: types are convertible.");
433 #ifdef DEBUG
434       if (FLAG_debug_code) {
435         if (std::is_same<PreviousType, MaybeObject>::value) {
436           code_assembler_->GenerateCheckMaybeObjectIsObject(node_, location_);
437         }
438         TNode<ExternalReference> function = code_assembler_->ExternalConstant(
439             ExternalReference::check_object_type());
440         code_assembler_->CallCFunction(
441             function, MachineType::AnyTagged(),
442             std::make_pair(MachineType::AnyTagged(), node_),
443             std::make_pair(MachineType::TaggedSigned(),
444                            code_assembler_->SmiConstant(
445                                static_cast<int>(ObjectTypeOf<A>::value))),
446             std::make_pair(MachineType::AnyTagged(),
447                            code_assembler_->StringConstant(location_)));
448       }
449 #endif
450       return TNode<A>::UncheckedCast(node_);
451     }
452 
453     template <class A>
454     operator SloppyTNode<A>() {
455       return implicit_cast<TNode<A>>(*this);
456     }
457 
node()458     Node* node() const { return node_; }
459 
460    private:
461     Node* node_;
462 #ifdef DEBUG
463     CodeAssembler* code_assembler_;
464     const char* location_;
465 #endif
466   };
467 
468   template <class T>
UncheckedCast(Node * value)469   TNode<T> UncheckedCast(Node* value) {
470     return TNode<T>::UncheckedCast(value);
471   }
472   template <class T, class U>
UncheckedCast(TNode<U> value)473   TNode<T> UncheckedCast(TNode<U> value) {
474     static_assert(types_have_common_values<T, U>::value,
475                   "Incompatible types: this cast can never succeed.");
476     return TNode<T>::UncheckedCast(value);
477   }
478 
479   // ReinterpretCast<T>(v) has the power to cast even when the type of v is
480   // unrelated to T. Use with care.
481   template <class T>
ReinterpretCast(Node * value)482   TNode<T> ReinterpretCast(Node* value) {
483     return TNode<T>::UncheckedCast(value);
484   }
485 
486   CheckedNode<Object, false> Cast(Node* value, const char* location = "") {
487     return {value, this, location};
488   }
489 
490   template <class T>
491   CheckedNode<T, true> Cast(TNode<T> value, const char* location = "") {
492     return {value, this, location};
493   }
494 
495 #ifdef DEBUG
496 #define STRINGIFY(x) #x
497 #define TO_STRING_LITERAL(x) STRINGIFY(x)
498 #define CAST(x) \
499   Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
500 #define TORQUE_CAST(x) \
501   ca_.Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
502 #else
503 #define CAST(x) Cast(x)
504 #define TORQUE_CAST(x) ca_.Cast(x)
505 #endif
506 
507 #ifdef DEBUG
508   void GenerateCheckMaybeObjectIsObject(Node* node, const char* location);
509 #endif
510 
511   // Constants.
512   TNode<Int32T> Int32Constant(int32_t value);
513   TNode<Int64T> Int64Constant(int64_t value);
514   TNode<IntPtrT> IntPtrConstant(intptr_t value);
Uint32Constant(uint32_t value)515   TNode<Uint32T> Uint32Constant(uint32_t value) {
516     return Unsigned(Int32Constant(bit_cast<int32_t>(value)));
517   }
UintPtrConstant(uintptr_t value)518   TNode<UintPtrT> UintPtrConstant(uintptr_t value) {
519     return Unsigned(IntPtrConstant(bit_cast<intptr_t>(value)));
520   }
521   TNode<TaggedIndex> TaggedIndexConstant(intptr_t value);
PointerConstant(void * value)522   TNode<RawPtrT> PointerConstant(void* value) {
523     return ReinterpretCast<RawPtrT>(IntPtrConstant(bit_cast<intptr_t>(value)));
524   }
525   TNode<Number> NumberConstant(double value);
526   TNode<Smi> SmiConstant(Smi value);
527   TNode<Smi> SmiConstant(int value);
528   template <typename E,
529             typename = typename std::enable_if<std::is_enum<E>::value>::type>
SmiConstant(E value)530   TNode<Smi> SmiConstant(E value) {
531     STATIC_ASSERT(sizeof(E) <= sizeof(int));
532     return SmiConstant(static_cast<int>(value));
533   }
534   TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
535   template <class Type>
HeapConstant(Handle<Type> object)536   TNode<Type> HeapConstant(Handle<Type> object) {
537     return UncheckedCast<Type>(UntypedHeapConstant(object));
538   }
539   TNode<String> StringConstant(const char* str);
540   TNode<Oddball> BooleanConstant(bool value);
541   TNode<ExternalReference> ExternalConstant(ExternalReference address);
542   TNode<Float32T> Float32Constant(double value);
543   TNode<Float64T> Float64Constant(double value);
Int32TrueConstant()544   TNode<BoolT> Int32TrueConstant() {
545     return ReinterpretCast<BoolT>(Int32Constant(1));
546   }
Int32FalseConstant()547   TNode<BoolT> Int32FalseConstant() {
548     return ReinterpretCast<BoolT>(Int32Constant(0));
549   }
BoolConstant(bool value)550   TNode<BoolT> BoolConstant(bool value) {
551     return value ? Int32TrueConstant() : Int32FalseConstant();
552   }
553 
554   bool ToInt32Constant(Node* node, int32_t* out_value);
555   bool ToInt64Constant(Node* node, int64_t* out_value);
556   bool ToIntPtrConstant(Node* node, intptr_t* out_value);
557   bool ToSmiConstant(Node* node, Smi* out_value);
558 
559   bool IsUndefinedConstant(TNode<Object> node);
560   bool IsNullConstant(TNode<Object> node);
561 
Signed(TNode<Word32T> x)562   TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
Signed(TNode<WordT> x)563   TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
Unsigned(TNode<Word32T> x)564   TNode<Uint32T> Unsigned(TNode<Word32T> x) {
565     return UncheckedCast<Uint32T>(x);
566   }
Unsigned(TNode<WordT> x)567   TNode<UintPtrT> Unsigned(TNode<WordT> x) {
568     return UncheckedCast<UintPtrT>(x);
569   }
570 
571   static constexpr int kTargetParameterIndex = -1;
572 
573   template <class T>
574   TNode<T> Parameter(
575       int value, cppgc::SourceLocation loc = cppgc::SourceLocation::Current()) {
576     static_assert(
577         std::is_convertible<TNode<T>, TNode<Object>>::value,
578         "Parameter is only for tagged types. Use UncheckedParameter instead.");
579     std::stringstream message;
580     message << "Parameter " << value;
581     if (loc.FileName()) {
582       message << " at " << loc.FileName() << ":" << loc.Line();
583     }
584     size_t buf_size = message.str().size() + 1;
585     char* message_dup = zone()->NewArray<char>(buf_size);
586     snprintf(message_dup, buf_size, "%s", message.str().c_str());
587 
588     return Cast(UntypedParameter(value), message_dup);
589   }
590 
591   template <class T>
UncheckedParameter(int value)592   TNode<T> UncheckedParameter(int value) {
593     return UncheckedCast<T>(UntypedParameter(value));
594   }
595 
596   Node* UntypedParameter(int value);
597 
598   TNode<Context> GetJSContextParameter();
599   void Return(TNode<Object> value);
600   void Return(TNode<Object> value1, TNode<Object> value2);
601   void Return(TNode<Object> value1, TNode<Object> value2, TNode<Object> value3);
602   void Return(TNode<Int32T> value);
603   void Return(TNode<Uint32T> value);
604   void Return(TNode<WordT> value);
605   void Return(TNode<Float32T> value);
606   void Return(TNode<Float64T> value);
607   void Return(TNode<WordT> value1, TNode<WordT> value2);
608   void PopAndReturn(Node* pop, Node* value);
609 
610   void ReturnIf(TNode<BoolT> condition, TNode<Object> value);
611 
612   void AbortCSAAssert(Node* message);
613   void DebugBreak();
614   void Unreachable();
Comment(const char * msg)615   void Comment(const char* msg) {
616     if (!FLAG_code_comments) return;
617     Comment(std::string(msg));
618   }
619   void Comment(std::string msg);
620   template <class... Args>
Comment(Args &&...args)621   void Comment(Args&&... args) {
622     if (!FLAG_code_comments) return;
623     std::ostringstream s;
624     USE((s << std::forward<Args>(args))...);
625     Comment(s.str());
626   }
627 
628   void StaticAssert(TNode<BoolT> value,
629                     const char* source = "unknown position");
630 
631   // The following methods refer to source positions in CSA or Torque code
632   // compiled during mksnapshot, not JS compiled at runtime.
633   void SetSourcePosition(const char* file, int line);
634   void PushSourcePosition();
635   void PopSourcePosition();
636   class SourcePositionScope {
637    public:
SourcePositionScope(CodeAssembler * ca)638     explicit SourcePositionScope(CodeAssembler* ca) : ca_(ca) {
639       ca->PushSourcePosition();
640     }
~SourcePositionScope()641     ~SourcePositionScope() { ca_->PopSourcePosition(); }
642 
643    private:
644     CodeAssembler* ca_;
645   };
646   const std::vector<FileAndLine>& GetMacroSourcePositionStack() const;
647 
648   void Bind(Label* label);
649 #if DEBUG
650   void Bind(Label* label, AssemblerDebugInfo debug_info);
651 #endif  // DEBUG
652   void Goto(Label* label);
653   void GotoIf(TNode<IntegralT> condition, Label* true_label);
654   void GotoIfNot(TNode<IntegralT> condition, Label* false_label);
655   void Branch(TNode<IntegralT> condition, Label* true_label,
656               Label* false_label);
657 
658   template <class T>
Uninitialized()659   TNode<T> Uninitialized() {
660     return {};
661   }
662 
663   template <class... T>
Bind(CodeAssemblerParameterizedLabel<T...> * label,TNode<T> * ...phis)664   void Bind(CodeAssemblerParameterizedLabel<T...>* label, TNode<T>*... phis) {
665     Bind(label->plain_label());
666     label->CreatePhis(phis...);
667   }
668   template <class... T, class... Args>
Branch(TNode<BoolT> condition,CodeAssemblerParameterizedLabel<T...> * if_true,CodeAssemblerParameterizedLabel<T...> * if_false,Args...args)669   void Branch(TNode<BoolT> condition,
670               CodeAssemblerParameterizedLabel<T...>* if_true,
671               CodeAssemblerParameterizedLabel<T...>* if_false, Args... args) {
672     if_true->AddInputs(args...);
673     if_false->AddInputs(args...);
674     Branch(condition, if_true->plain_label(), if_false->plain_label());
675   }
676   template <class... T, class... U>
Branch(TNode<BoolT> condition,CodeAssemblerParameterizedLabel<T...> * if_true,std::vector<Node * > args_true,CodeAssemblerParameterizedLabel<U...> * if_false,std::vector<Node * > args_false)677   void Branch(TNode<BoolT> condition,
678               CodeAssemblerParameterizedLabel<T...>* if_true,
679               std::vector<Node*> args_true,
680               CodeAssemblerParameterizedLabel<U...>* if_false,
681               std::vector<Node*> args_false) {
682     if_true->AddInputsVector(std::move(args_true));
683     if_false->AddInputsVector(std::move(args_false));
684     Branch(condition, if_true->plain_label(), if_false->plain_label());
685   }
686 
687   template <class... T, class... Args>
Goto(CodeAssemblerParameterizedLabel<T...> * label,Args...args)688   void Goto(CodeAssemblerParameterizedLabel<T...>* label, Args... args) {
689     label->AddInputs(args...);
690     Goto(label->plain_label());
691   }
692 
693   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
694               const std::function<void()>& false_body);
695   void Branch(TNode<BoolT> condition, Label* true_label,
696               const std::function<void()>& false_body);
697   void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
698               Label* false_label);
699 
700   void Switch(Node* index, Label* default_label, const int32_t* case_values,
701               Label** case_labels, size_t case_count);
702 
703   // Access to the frame pointer
704   TNode<RawPtrT> LoadFramePointer();
705   TNode<RawPtrT> LoadParentFramePointer();
706 
707   // Poison |value| on speculative paths.
708   TNode<Object> TaggedPoisonOnSpeculation(TNode<Object> value);
709   TNode<WordT> WordPoisonOnSpeculation(TNode<WordT> value);
710 
711   // Load raw memory location.
712   Node* Load(MachineType type, Node* base,
713              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
714   template <class Type>
Load(MachineType type,TNode<RawPtr<Type>> base)715   TNode<Type> Load(MachineType type, TNode<RawPtr<Type>> base) {
716     DCHECK(
717         IsSubtype(type.representation(), MachineRepresentationOf<Type>::value));
718     return UncheckedCast<Type>(Load(type, static_cast<Node*>(base)));
719   }
720   Node* Load(MachineType type, Node* base, Node* offset,
721              LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
722   template <class Type>
723   TNode<Type> Load(Node* base,
724                    LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
725     return UncheckedCast<Type>(
726         Load(MachineTypeOf<Type>::value, base, needs_poisoning));
727   }
728   template <class Type>
729   TNode<Type> Load(Node* base, SloppyTNode<WordT> offset,
730                    LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
731     return UncheckedCast<Type>(
732         Load(MachineTypeOf<Type>::value, base, offset, needs_poisoning));
733   }
734   Node* AtomicLoad(MachineType type, Node* base, Node* offset);
735   // Load uncompressed tagged value from (most likely off JS heap) memory
736   // location.
737   TNode<Object> LoadFullTagged(
738       Node* base, LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
739   TNode<Object> LoadFullTagged(
740       Node* base, Node* offset,
741       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
742 
743   Node* LoadFromObject(MachineType type, TNode<HeapObject> object,
744                        TNode<IntPtrT> offset);
745 
746   // Load a value from the root array.
747   TNode<Object> LoadRoot(RootIndex root_index);
748 
749   // Store value to raw memory location.
750   Node* Store(Node* base, Node* value);
751   Node* Store(Node* base, Node* offset, Node* value);
752   Node* StoreEphemeronKey(Node* base, Node* offset, Node* value);
753   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
754   Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
755                             Node* value);
756   Node* UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
757                                   Node* value);
758   Node* UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
759                                   Node* offset, Node* value);
760 
761   // Stores uncompressed tagged value to (most likely off JS heap) memory
762   // location without write barrier.
763   Node* StoreFullTaggedNoWriteBarrier(Node* base, Node* tagged_value);
764   Node* StoreFullTaggedNoWriteBarrier(Node* base, Node* offset,
765                                       Node* tagged_value);
766 
767   // Optimized memory operations that map to Turbofan simplified nodes.
768   TNode<HeapObject> OptimizedAllocate(TNode<IntPtrT> size,
769                                       AllocationType allocation,
770                                       AllowLargeObjects allow_large_objects);
771   void StoreToObject(MachineRepresentation rep, TNode<HeapObject> object,
772                      TNode<IntPtrT> offset, Node* value,
773                      StoreToObjectWriteBarrier write_barrier);
774   void OptimizedStoreField(MachineRepresentation rep, TNode<HeapObject> object,
775                            int offset, Node* value);
776   void OptimizedStoreFieldAssertNoWriteBarrier(MachineRepresentation rep,
777                                                TNode<HeapObject> object,
778                                                int offset, Node* value);
779   void OptimizedStoreFieldUnsafeNoWriteBarrier(MachineRepresentation rep,
780                                                TNode<HeapObject> object,
781                                                int offset, Node* value);
782   void OptimizedStoreMap(TNode<HeapObject> object, TNode<Map>);
783   // {value_high} is used for 64-bit stores on 32-bit platforms, must be
784   // nullptr in other cases.
785   Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
786                     Node* value, Node* value_high = nullptr);
787 
788   Node* AtomicAdd(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
789                   Node* value, base::Optional<TNode<UintPtrT>> value_high);
790 
791   Node* AtomicSub(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
792                   Node* value, base::Optional<TNode<UintPtrT>> value_high);
793 
794   Node* AtomicAnd(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
795                   Node* value, base::Optional<TNode<UintPtrT>> value_high);
796 
797   Node* AtomicOr(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
798                  Node* value, base::Optional<TNode<UintPtrT>> value_high);
799 
800   Node* AtomicXor(MachineType type, TNode<RawPtrT> base, TNode<UintPtrT> offset,
801                   Node* value, base::Optional<TNode<UintPtrT>> value_high);
802 
803   // Exchange value at raw memory location
804   Node* AtomicExchange(MachineType type, TNode<RawPtrT> base,
805                        TNode<UintPtrT> offset, Node* value,
806                        base::Optional<TNode<UintPtrT>> value_high);
807 
808   // Compare and Exchange value at raw memory location
809   Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
810                               Node* old_value, Node* new_value,
811                               Node* old_value_high = nullptr,
812                               Node* new_value_high = nullptr);
813   // Store a value to the root array.
814   Node* StoreRoot(RootIndex root_index, Node* value);
815 
816 // Basic arithmetic operations.
817 #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
818   TNode<ResType> name(SloppyTNode<Arg1Type> a, SloppyTNode<Arg2Type> b);
CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)819   CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
820 #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
821 
822   TNode<UintPtrT> WordShr(TNode<UintPtrT> left, TNode<IntegralT> right) {
823     return Unsigned(
824         WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
825   }
WordSar(TNode<IntPtrT> left,TNode<IntegralT> right)826   TNode<IntPtrT> WordSar(TNode<IntPtrT> left, TNode<IntegralT> right) {
827     return Signed(WordSar(static_cast<Node*>(left), static_cast<Node*>(right)));
828   }
WordShl(TNode<IntPtrT> left,TNode<IntegralT> right)829   TNode<IntPtrT> WordShl(TNode<IntPtrT> left, TNode<IntegralT> right) {
830     return Signed(WordShl(static_cast<Node*>(left), static_cast<Node*>(right)));
831   }
WordShl(TNode<UintPtrT> left,TNode<IntegralT> right)832   TNode<UintPtrT> WordShl(TNode<UintPtrT> left, TNode<IntegralT> right) {
833     return Unsigned(
834         WordShl(static_cast<Node*>(left), static_cast<Node*>(right)));
835   }
836 
Word32Shl(TNode<Int32T> left,TNode<Int32T> right)837   TNode<Int32T> Word32Shl(TNode<Int32T> left, TNode<Int32T> right) {
838     return Signed(
839         Word32Shl(static_cast<Node*>(left), static_cast<Node*>(right)));
840   }
Word32Shl(TNode<Uint32T> left,TNode<Uint32T> right)841   TNode<Uint32T> Word32Shl(TNode<Uint32T> left, TNode<Uint32T> right) {
842     return Unsigned(
843         Word32Shl(static_cast<Node*>(left), static_cast<Node*>(right)));
844   }
Word32Shr(TNode<Uint32T> left,TNode<Uint32T> right)845   TNode<Uint32T> Word32Shr(TNode<Uint32T> left, TNode<Uint32T> right) {
846     return Unsigned(
847         Word32Shr(static_cast<Node*>(left), static_cast<Node*>(right)));
848   }
Word32Sar(TNode<Int32T> left,TNode<Int32T> right)849   TNode<Int32T> Word32Sar(TNode<Int32T> left, TNode<Int32T> right) {
850     return Signed(
851         Word32Sar(static_cast<Node*>(left), static_cast<Node*>(right)));
852   }
853 
WordAnd(TNode<IntPtrT> left,TNode<IntPtrT> right)854   TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
855     return Signed(WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
856   }
WordAnd(TNode<UintPtrT> left,TNode<UintPtrT> right)857   TNode<UintPtrT> WordAnd(TNode<UintPtrT> left, TNode<UintPtrT> right) {
858     return Unsigned(
859         WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
860   }
861 
Word32And(TNode<Int32T> left,TNode<Int32T> right)862   TNode<Int32T> Word32And(TNode<Int32T> left, TNode<Int32T> right) {
863     return Signed(
864         Word32And(static_cast<Node*>(left), static_cast<Node*>(right)));
865   }
Word32And(TNode<Uint32T> left,TNode<Uint32T> right)866   TNode<Uint32T> Word32And(TNode<Uint32T> left, TNode<Uint32T> right) {
867     return Unsigned(
868         Word32And(static_cast<Node*>(left), static_cast<Node*>(right)));
869   }
870 
Word32Or(TNode<Int32T> left,TNode<Int32T> right)871   TNode<Int32T> Word32Or(TNode<Int32T> left, TNode<Int32T> right) {
872     return Signed(
873         Word32Or(static_cast<Node*>(left), static_cast<Node*>(right)));
874   }
Word32Or(TNode<Uint32T> left,TNode<Uint32T> right)875   TNode<Uint32T> Word32Or(TNode<Uint32T> left, TNode<Uint32T> right) {
876     return Unsigned(
877         Word32Or(static_cast<Node*>(left), static_cast<Node*>(right)));
878   }
879 
880   TNode<BoolT> IntPtrEqual(TNode<WordT> left, TNode<WordT> right);
881   TNode<BoolT> WordEqual(TNode<WordT> left, TNode<WordT> right);
882   TNode<BoolT> WordNotEqual(TNode<WordT> left, TNode<WordT> right);
883   TNode<BoolT> Word32Equal(TNode<Word32T> left, TNode<Word32T> right);
884   TNode<BoolT> Word32NotEqual(TNode<Word32T> left, TNode<Word32T> right);
885   TNode<BoolT> Word64Equal(TNode<Word64T> left, TNode<Word64T> right);
886   TNode<BoolT> Word64NotEqual(TNode<Word64T> left, TNode<Word64T> right);
887 
Word32Or(TNode<BoolT> left,TNode<BoolT> right)888   TNode<BoolT> Word32Or(TNode<BoolT> left, TNode<BoolT> right) {
889     return UncheckedCast<BoolT>(
890         Word32Or(static_cast<Node*>(left), static_cast<Node*>(right)));
891   }
Word32And(TNode<BoolT> left,TNode<BoolT> right)892   TNode<BoolT> Word32And(TNode<BoolT> left, TNode<BoolT> right) {
893     return UncheckedCast<BoolT>(
894         Word32And(static_cast<Node*>(left), static_cast<Node*>(right)));
895   }
896 
Int32Add(TNode<Int32T> left,TNode<Int32T> right)897   TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
898     return Signed(
899         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
900   }
901 
Uint32Add(TNode<Uint32T> left,TNode<Uint32T> right)902   TNode<Uint32T> Uint32Add(TNode<Uint32T> left, TNode<Uint32T> right) {
903     return Unsigned(
904         Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
905   }
906 
Int32Sub(TNode<Int32T> left,TNode<Int32T> right)907   TNode<Int32T> Int32Sub(TNode<Int32T> left, TNode<Int32T> right) {
908     return Signed(
909         Int32Sub(static_cast<Node*>(left), static_cast<Node*>(right)));
910   }
911 
Int32Mul(TNode<Int32T> left,TNode<Int32T> right)912   TNode<Int32T> Int32Mul(TNode<Int32T> left, TNode<Int32T> right) {
913     return Signed(
914         Int32Mul(static_cast<Node*>(left), static_cast<Node*>(right)));
915   }
916 
IntPtrAdd(TNode<IntPtrT> left,TNode<IntPtrT> right)917   TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
918     return Signed(
919         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
920   }
IntPtrSub(TNode<IntPtrT> left,TNode<IntPtrT> right)921   TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
922     return Signed(
923         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
924   }
IntPtrMul(TNode<IntPtrT> left,TNode<IntPtrT> right)925   TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
926     return Signed(
927         IntPtrMul(static_cast<Node*>(left), static_cast<Node*>(right)));
928   }
UintPtrAdd(TNode<UintPtrT> left,TNode<UintPtrT> right)929   TNode<UintPtrT> UintPtrAdd(TNode<UintPtrT> left, TNode<UintPtrT> right) {
930     return Unsigned(
931         IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
932   }
UintPtrSub(TNode<UintPtrT> left,TNode<UintPtrT> right)933   TNode<UintPtrT> UintPtrSub(TNode<UintPtrT> left, TNode<UintPtrT> right) {
934     return Unsigned(
935         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
936   }
RawPtrAdd(TNode<RawPtrT> left,TNode<IntPtrT> right)937   TNode<RawPtrT> RawPtrAdd(TNode<RawPtrT> left, TNode<IntPtrT> right) {
938     return ReinterpretCast<RawPtrT>(IntPtrAdd(left, right));
939   }
RawPtrSub(TNode<RawPtrT> left,TNode<IntPtrT> right)940   TNode<RawPtrT> RawPtrSub(TNode<RawPtrT> left, TNode<IntPtrT> right) {
941     return ReinterpretCast<RawPtrT>(IntPtrSub(left, right));
942   }
RawPtrSub(TNode<RawPtrT> left,TNode<RawPtrT> right)943   TNode<IntPtrT> RawPtrSub(TNode<RawPtrT> left, TNode<RawPtrT> right) {
944     return Signed(
945         IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
946   }
947 
948   TNode<WordT> WordShl(SloppyTNode<WordT> value, int shift);
949   TNode<WordT> WordShr(SloppyTNode<WordT> value, int shift);
950   TNode<WordT> WordSar(SloppyTNode<WordT> value, int shift);
WordShr(TNode<IntPtrT> value,int shift)951   TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
952     return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
953   }
WordSar(TNode<IntPtrT> value,int shift)954   TNode<IntPtrT> WordSar(TNode<IntPtrT> value, int shift) {
955     return UncheckedCast<IntPtrT>(WordSar(static_cast<Node*>(value), shift));
956   }
957   TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
958   TNode<Word32T> Word32Sar(SloppyTNode<Word32T> value, int shift);
959 
960 // Unary
961 #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
962   TNode<ResType> name(SloppyTNode<ArgType> a);
CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)963   CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
964 #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
965 
966   template <class Dummy = void>
967   TNode<IntPtrT> BitcastTaggedToWord(TNode<Smi> node) {
968     static_assert(sizeof(Dummy) < 0,
969                   "Should use BitcastTaggedToWordForTagAndSmiBits instead.");
970   }
971 
972   // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
973   // Assumes that the double can be exactly represented as an int.
974   TNode<IntPtrT> ChangeFloat64ToIntPtr(TNode<Float64T> value);
975   TNode<UintPtrT> ChangeFloat64ToUintPtr(TNode<Float64T> value);
976   // Same in the opposite direction.
977   TNode<Float64T> ChangeUintPtrToFloat64(TNode<UintPtrT> value);
978 
979   // Changes an intptr_t to a double, e.g. for storing an element index
980   // outside Smi range in a HeapNumber. Lossless on 32-bit,
981   // rounds on 64-bit (which doesn't affect valid element indices).
982   TNode<Float64T> RoundIntPtrToFloat64(Node* value);
983   // No-op on 32-bit, otherwise zero extend.
984   TNode<UintPtrT> ChangeUint32ToWord(TNode<Word32T> value);
985   // No-op on 32-bit, otherwise sign extend.
986   TNode<IntPtrT> ChangeInt32ToIntPtr(TNode<Word32T> value);
987 
988   // Truncates a float to a 32-bit integer. If the float is outside of 32-bit
989   // range, make sure that overflow detection is easy. In particular, return
990   // int_min instead of int_max on arm platforms by using parameter
991   // kSetOverflowToMin.
992   TNode<Int32T> TruncateFloat32ToInt32(SloppyTNode<Float32T> value);
993 
994   // Projections
995   Node* Projection(int index, Node* value);
996 
997   template <int index, class T1, class T2>
998   TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
Projection(TNode<PairT<T1,T2>> value)999   Projection(TNode<PairT<T1, T2>> value) {
1000     return UncheckedCast<
1001         typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
1002         Projection(index, value));
1003   }
1004 
1005   // Calls
1006   template <class T = Object, class... TArgs>
CallRuntime(Runtime::FunctionId function,TNode<Object> context,TArgs...args)1007   TNode<T> CallRuntime(Runtime::FunctionId function, TNode<Object> context,
1008                        TArgs... args) {
1009     return UncheckedCast<T>(CallRuntimeImpl(
1010         function, context, {implicit_cast<TNode<Object>>(args)...}));
1011   }
1012 
1013   template <class... TArgs>
TailCallRuntime(Runtime::FunctionId function,TNode<Object> context,TArgs...args)1014   void TailCallRuntime(Runtime::FunctionId function, TNode<Object> context,
1015                        TArgs... args) {
1016     int argc = static_cast<int>(sizeof...(args));
1017     TNode<Int32T> arity = Int32Constant(argc);
1018     return TailCallRuntimeImpl(function, arity, context,
1019                                {implicit_cast<TNode<Object>>(args)...});
1020   }
1021 
1022   template <class... TArgs>
TailCallRuntime(Runtime::FunctionId function,TNode<Int32T> arity,TNode<Object> context,TArgs...args)1023   void TailCallRuntime(Runtime::FunctionId function, TNode<Int32T> arity,
1024                        TNode<Object> context, TArgs... args) {
1025     return TailCallRuntimeImpl(function, arity, context,
1026                                {implicit_cast<TNode<Object>>(args)...});
1027   }
1028 
1029   //
1030   // If context passed to CallStub is nullptr, it won't be passed to the stub.
1031   //
1032 
1033   template <class T = Object, class... TArgs>
CallStub(Callable const & callable,TNode<Object> context,TArgs...args)1034   TNode<T> CallStub(Callable const& callable, TNode<Object> context,
1035                     TArgs... args) {
1036     TNode<Code> target = HeapConstant(callable.code());
1037     return CallStub<T>(callable.descriptor(), target, context, args...);
1038   }
1039 
1040   template <class T = Object, class... TArgs>
CallStub(const CallInterfaceDescriptor & descriptor,TNode<Code> target,TNode<Object> context,TArgs...args)1041   TNode<T> CallStub(const CallInterfaceDescriptor& descriptor,
1042                     TNode<Code> target, TNode<Object> context, TArgs... args) {
1043     return UncheckedCast<T>(CallStubR(StubCallMode::kCallCodeObject, descriptor,
1044                                       target, context, args...));
1045   }
1046 
1047   template <class T = Object, class... TArgs>
CallBuiltinPointer(const CallInterfaceDescriptor & descriptor,TNode<BuiltinPtr> target,TNode<Object> context,TArgs...args)1048   TNode<T> CallBuiltinPointer(const CallInterfaceDescriptor& descriptor,
1049                               TNode<BuiltinPtr> target, TNode<Object> context,
1050                               TArgs... args) {
1051     return UncheckedCast<T>(CallStubR(StubCallMode::kCallBuiltinPointer,
1052                                       descriptor, target, context, args...));
1053   }
1054 
1055   template <class... TArgs>
TailCallStub(Callable const & callable,TNode<Object> context,TArgs...args)1056   void TailCallStub(Callable const& callable, TNode<Object> context,
1057                     TArgs... args) {
1058     TNode<Code> target = HeapConstant(callable.code());
1059     TailCallStub(callable.descriptor(), target, context, args...);
1060   }
1061 
1062   template <class... TArgs>
TailCallStub(const CallInterfaceDescriptor & descriptor,TNode<Code> target,TNode<Object> context,TArgs...args)1063   void TailCallStub(const CallInterfaceDescriptor& descriptor,
1064                     TNode<Code> target, TNode<Object> context, TArgs... args) {
1065     TailCallStubImpl(descriptor, target, context, {args...});
1066   }
1067 
1068   template <class... TArgs>
1069   void TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
1070                                 TNode<RawPtrT> target, TArgs... args);
1071 
1072   template <class... TArgs>
TailCallStubThenBytecodeDispatch(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,TArgs...args)1073   void TailCallStubThenBytecodeDispatch(
1074       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1075       TArgs... args) {
1076     TailCallStubThenBytecodeDispatchImpl(descriptor, target, context,
1077                                          {args...});
1078   }
1079 
1080   // Tailcalls to the given code object with JSCall linkage. The JS arguments
1081   // (including receiver) are supposed to be already on the stack.
1082   // This is a building block for implementing trampoline stubs that are
1083   // installed instead of code objects with JSCall linkage.
1084   // Note that no arguments adaption is going on here - all the JavaScript
1085   // arguments are left on the stack unmodified. Therefore, this tail call can
1086   // only be used after arguments adaptation has been performed already.
1087   void TailCallJSCode(TNode<Code> code, TNode<Context> context,
1088                       TNode<JSFunction> function, TNode<Object> new_target,
1089                       TNode<Int32T> arg_count);
1090 
1091   template <class... TArgs>
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,TArgs...args)1092   TNode<Object> CallJS(Callable const& callable, Node* context, Node* function,
1093                        Node* receiver, TArgs... args) {
1094     int argc = static_cast<int>(sizeof...(args));
1095     TNode<Int32T> arity = Int32Constant(argc);
1096     TNode<Code> target = HeapConstant(callable.code());
1097     return CAST(CallJSStubImpl(callable.descriptor(), target, CAST(context),
1098                                CAST(function), TNode<Object>(), arity,
1099                                {receiver, args...}));
1100   }
1101 
1102   template <class... TArgs>
ConstructJSWithTarget(Callable const & callable,Node * context,Node * function,Node * new_target,TArgs...args)1103   Node* ConstructJSWithTarget(Callable const& callable, Node* context,
1104                               Node* function, Node* new_target, TArgs... args) {
1105     int argc = static_cast<int>(sizeof...(args));
1106     TNode<Int32T> arity = Int32Constant(argc);
1107     TNode<Object> receiver = LoadRoot(RootIndex::kUndefinedValue);
1108     TNode<Code> target = HeapConstant(callable.code());
1109     return CallJSStubImpl(callable.descriptor(), target, CAST(context),
1110                           CAST(function), CAST(new_target), arity,
1111                           {receiver, args...});
1112   }
1113   template <class... TArgs>
ConstructJS(Callable const & callable,Node * context,Node * new_target,TArgs...args)1114   Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
1115                     TArgs... args) {
1116     return ConstructJSWithTarget(callable, context, new_target, new_target,
1117                                  args...);
1118   }
1119 
1120   Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
1121                        Node* const* inputs);
1122 
1123   // Type representing C function argument with type info.
1124   using CFunctionArg = std::pair<MachineType, Node*>;
1125 
1126   // Call to a C function.
1127   template <class... CArgs>
CallCFunction(Node * function,MachineType return_type,CArgs...cargs)1128   Node* CallCFunction(Node* function, MachineType return_type, CArgs... cargs) {
1129     static_assert(v8::internal::conjunction<
1130                       std::is_convertible<CArgs, CFunctionArg>...>::value,
1131                   "invalid argument types");
1132     return CallCFunction(function, return_type, {cargs...});
1133   }
1134 
1135   // Call to a C function without a function discriptor on AIX.
1136   template <class... CArgs>
CallCFunctionWithoutFunctionDescriptor(Node * function,MachineType return_type,CArgs...cargs)1137   Node* CallCFunctionWithoutFunctionDescriptor(Node* function,
1138                                                MachineType return_type,
1139                                                CArgs... cargs) {
1140     static_assert(v8::internal::conjunction<
1141                       std::is_convertible<CArgs, CFunctionArg>...>::value,
1142                   "invalid argument types");
1143     return CallCFunctionWithoutFunctionDescriptor(function, return_type,
1144                                                   {cargs...});
1145   }
1146 
1147   // Call to a C function, while saving/restoring caller registers.
1148   template <class... CArgs>
CallCFunctionWithCallerSavedRegisters(Node * function,MachineType return_type,SaveFPRegsMode mode,CArgs...cargs)1149   Node* CallCFunctionWithCallerSavedRegisters(Node* function,
1150                                               MachineType return_type,
1151                                               SaveFPRegsMode mode,
1152                                               CArgs... cargs) {
1153     static_assert(v8::internal::conjunction<
1154                       std::is_convertible<CArgs, CFunctionArg>...>::value,
1155                   "invalid argument types");
1156     return CallCFunctionWithCallerSavedRegisters(function, return_type, mode,
1157                                                  {cargs...});
1158   }
1159 
1160   // Helpers which delegate to RawMachineAssembler.
1161   Factory* factory() const;
1162   Isolate* isolate() const;
1163   Zone* zone() const;
1164 
state()1165   CodeAssemblerState* state() { return state_; }
1166 
1167   void BreakOnNode(int node_id);
1168 
1169   bool UnalignedLoadSupported(MachineRepresentation rep) const;
1170   bool UnalignedStoreSupported(MachineRepresentation rep) const;
1171 
1172   bool IsExceptionHandlerActive() const;
1173 
1174  protected:
1175   void RegisterCallGenerationCallbacks(
1176       const CodeAssemblerCallback& call_prologue,
1177       const CodeAssemblerCallback& call_epilogue);
1178   void UnregisterCallGenerationCallbacks();
1179 
1180   bool Word32ShiftIsSafe() const;
1181   PoisoningMitigationLevel poisoning_level() const;
1182 
1183   bool IsJSFunctionCall() const;
1184 
1185  private:
1186   void HandleException(Node* result);
1187 
1188   Node* CallCFunction(Node* function, MachineType return_type,
1189                       std::initializer_list<CFunctionArg> args);
1190 
1191   Node* CallCFunctionWithoutFunctionDescriptor(
1192       Node* function, MachineType return_type,
1193       std::initializer_list<CFunctionArg> args);
1194 
1195   Node* CallCFunctionWithCallerSavedRegisters(
1196       Node* function, MachineType return_type, SaveFPRegsMode mode,
1197       std::initializer_list<CFunctionArg> args);
1198 
1199   Node* CallRuntimeImpl(Runtime::FunctionId function, TNode<Object> context,
1200                         std::initializer_list<TNode<Object>> args);
1201 
1202   void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
1203                            TNode<Object> context,
1204                            std::initializer_list<TNode<Object>> args);
1205 
1206   void TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
1207                         TNode<Code> target, TNode<Object> context,
1208                         std::initializer_list<Node*> args);
1209 
1210   void TailCallStubThenBytecodeDispatchImpl(
1211       const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1212       std::initializer_list<Node*> args);
1213 
1214   template <class... TArgs>
CallStubR(StubCallMode call_mode,const CallInterfaceDescriptor & descriptor,TNode<Object> target,TNode<Object> context,TArgs...args)1215   Node* CallStubR(StubCallMode call_mode,
1216                   const CallInterfaceDescriptor& descriptor,
1217                   TNode<Object> target, TNode<Object> context, TArgs... args) {
1218     return CallStubRImpl(call_mode, descriptor, target, context, {args...});
1219   }
1220 
1221   Node* CallStubRImpl(StubCallMode call_mode,
1222                       const CallInterfaceDescriptor& descriptor,
1223                       TNode<Object> target, TNode<Object> context,
1224                       std::initializer_list<Node*> args);
1225 
1226   Node* CallJSStubImpl(const CallInterfaceDescriptor& descriptor,
1227                        TNode<Object> target, TNode<Object> context,
1228                        TNode<Object> function, TNode<Object> new_target,
1229                        TNode<Int32T> arity, std::initializer_list<Node*> args);
1230 
1231   Node* CallStubN(StubCallMode call_mode,
1232                   const CallInterfaceDescriptor& descriptor, int input_count,
1233                   Node* const* inputs);
1234 
1235   // These two don't have definitions and are here only for catching use cases
1236   // where the cast is not necessary.
1237   TNode<Int32T> Signed(TNode<Int32T> x);
1238   TNode<Uint32T> Unsigned(TNode<Uint32T> x);
1239 
1240   RawMachineAssembler* raw_assembler() const;
1241   JSGraph* jsgraph() const;
1242 
1243   // Calls respective callback registered in the state.
1244   void CallPrologue();
1245   void CallEpilogue();
1246 
1247   CodeAssemblerState* state_;
1248 };
1249 
1250 // TODO(solanes, v8:6949): this class should be merged into
1251 // TypedCodeAssemblerVariable. It's required to be separate for
1252 // CodeAssemblerVariableLists.
1253 class V8_EXPORT_PRIVATE CodeAssemblerVariable {
1254  public:
1255   CodeAssemblerVariable(const CodeAssemblerVariable&) = delete;
1256   CodeAssemblerVariable& operator=(const CodeAssemblerVariable&) = delete;
1257 
1258   Node* value() const;
1259   MachineRepresentation rep() const;
1260   bool IsBound() const;
1261 
1262  protected:
1263   explicit CodeAssemblerVariable(CodeAssembler* assembler,
1264                                  MachineRepresentation rep);
1265   CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
1266                         Node* initial_value);
1267 #if DEBUG
1268   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1269                         MachineRepresentation rep);
1270   CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1271                         MachineRepresentation rep, Node* initial_value);
1272 #endif  // DEBUG
1273 
1274   ~CodeAssemblerVariable();
1275   void Bind(Node* value);
1276 
1277  private:
1278   class Impl;
1279   friend class CodeAssemblerLabel;
1280   friend class CodeAssemblerState;
1281   friend std::ostream& operator<<(std::ostream&, const Impl&);
1282   friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1283   struct ImplComparator {
1284     bool operator()(const CodeAssemblerVariable::Impl* a,
1285                     const CodeAssemblerVariable::Impl* b) const;
1286   };
1287   Impl* impl_;
1288   CodeAssemblerState* state_;
1289 };
1290 
1291 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1292 std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
1293 
1294 template <class T>
1295 class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
1296  public:
TypedCodeAssemblerVariable(TNode<T> initial_value,CodeAssembler * assembler)1297   TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
1298       : CodeAssemblerVariable(assembler, PhiMachineRepresentationOf<T>,
1299                               initial_value) {}
TypedCodeAssemblerVariable(CodeAssembler * assembler)1300   explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
1301       : CodeAssemblerVariable(assembler, PhiMachineRepresentationOf<T>) {}
1302 #if DEBUG
TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,CodeAssembler * assembler)1303   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1304                              CodeAssembler* assembler)
1305       : CodeAssemblerVariable(assembler, debug_info,
1306                               PhiMachineRepresentationOf<T>) {}
TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,TNode<T> initial_value,CodeAssembler * assembler)1307   TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1308                              TNode<T> initial_value, CodeAssembler* assembler)
1309       : CodeAssemblerVariable(assembler, debug_info,
1310                               PhiMachineRepresentationOf<T>, initial_value) {}
1311 #endif  // DEBUG
1312 
value()1313   TNode<T> value() const {
1314     return TNode<T>::UncheckedCast(CodeAssemblerVariable::value());
1315   }
1316 
1317   void operator=(TNode<T> value) { Bind(value); }
1318   void operator=(const TypedCodeAssemblerVariable<T>& variable) {
1319     Bind(variable.value());
1320   }
1321 
1322  private:
1323   using CodeAssemblerVariable::Bind;
1324 };
1325 
1326 class V8_EXPORT_PRIVATE CodeAssemblerLabel {
1327  public:
1328   enum Type { kDeferred, kNonDeferred };
1329 
1330   explicit CodeAssemblerLabel(
1331       CodeAssembler* assembler,
1332       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1333       : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
1334   CodeAssemblerLabel(
1335       CodeAssembler* assembler,
1336       const CodeAssemblerVariableList& merged_variables,
1337       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1338       : CodeAssemblerLabel(assembler, merged_variables.size(),
1339                            &(merged_variables[0]), type) {}
1340   CodeAssemblerLabel(
1341       CodeAssembler* assembler, size_t count,
1342       CodeAssemblerVariable* const* vars,
1343       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
1344   CodeAssemblerLabel(
1345       CodeAssembler* assembler,
1346       std::initializer_list<CodeAssemblerVariable*> vars,
1347       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1348       : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
1349   CodeAssemblerLabel(
1350       CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
1351       CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1352       : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
1353   ~CodeAssemblerLabel();
1354 
1355   // Cannot be copied because the destructor explicitly call the destructor of
1356   // the underlying {RawMachineLabel}, hence only one pointer can point to it.
1357   CodeAssemblerLabel(const CodeAssemblerLabel&) = delete;
1358   CodeAssemblerLabel& operator=(const CodeAssemblerLabel&) = delete;
1359 
is_bound()1360   inline bool is_bound() const { return bound_; }
is_used()1361   inline bool is_used() const { return merge_count_ != 0; }
1362 
1363  private:
1364   friend class CodeAssembler;
1365 
1366   void Bind();
1367 #if DEBUG
1368   void Bind(AssemblerDebugInfo debug_info);
1369 #endif  // DEBUG
1370   void UpdateVariablesAfterBind();
1371   void MergeVariables();
1372 
1373   bool bound_;
1374   size_t merge_count_;
1375   CodeAssemblerState* state_;
1376   RawMachineLabel* label_;
1377   // Map of variables that need to be merged to their phi nodes (or placeholders
1378   // for those phis).
1379   std::map<CodeAssemblerVariable::Impl*, Node*,
1380            CodeAssemblerVariable::ImplComparator>
1381       variable_phis_;
1382   // Map of variables to the list of value nodes that have been added from each
1383   // merge path in their order of merging.
1384   std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>,
1385            CodeAssemblerVariable::ImplComparator>
1386       variable_merges_;
1387 };
1388 
1389 class CodeAssemblerParameterizedLabelBase {
1390  public:
is_used()1391   bool is_used() const { return plain_label_.is_used(); }
CodeAssemblerParameterizedLabelBase(CodeAssembler * assembler,size_t arity,CodeAssemblerLabel::Type type)1392   explicit CodeAssemblerParameterizedLabelBase(CodeAssembler* assembler,
1393                                                size_t arity,
1394                                                CodeAssemblerLabel::Type type)
1395       : state_(assembler->state()),
1396         phi_inputs_(arity),
1397         plain_label_(assembler, type) {}
1398 
1399  protected:
plain_label()1400   CodeAssemblerLabel* plain_label() { return &plain_label_; }
1401   void AddInputs(std::vector<Node*> inputs);
1402   Node* CreatePhi(MachineRepresentation rep, const std::vector<Node*>& inputs);
1403   const std::vector<Node*>& CreatePhis(
1404       std::vector<MachineRepresentation> representations);
1405 
1406  private:
1407   CodeAssemblerState* state_;
1408   std::vector<std::vector<Node*>> phi_inputs_;
1409   std::vector<Node*> phi_nodes_;
1410   CodeAssemblerLabel plain_label_;
1411 };
1412 
1413 template <class... Types>
1414 class CodeAssemblerParameterizedLabel
1415     : public CodeAssemblerParameterizedLabelBase {
1416  public:
1417   static constexpr size_t kArity = sizeof...(Types);
CodeAssemblerParameterizedLabel(CodeAssembler * assembler,CodeAssemblerLabel::Type type)1418   explicit CodeAssemblerParameterizedLabel(CodeAssembler* assembler,
1419                                            CodeAssemblerLabel::Type type)
1420       : CodeAssemblerParameterizedLabelBase(assembler, kArity, type) {}
1421 
1422  private:
1423   friend class CodeAssembler;
1424 
AddInputsVector(std::vector<Node * > inputs)1425   void AddInputsVector(std::vector<Node*> inputs) {
1426     CodeAssemblerParameterizedLabelBase::AddInputs(std::move(inputs));
1427   }
AddInputs(TNode<Types>...inputs)1428   void AddInputs(TNode<Types>... inputs) {
1429     CodeAssemblerParameterizedLabelBase::AddInputs(
1430         std::vector<Node*>{inputs...});
1431   }
CreatePhis(TNode<Types> * ...results)1432   void CreatePhis(TNode<Types>*... results) {
1433     const std::vector<Node*>& phi_nodes =
1434         CodeAssemblerParameterizedLabelBase::CreatePhis(
1435             {PhiMachineRepresentationOf<Types>...});
1436     auto it = phi_nodes.begin();
1437     USE(it);
1438     ITERATE_PACK(AssignPhi(results, *(it++)));
1439   }
1440   template <class T>
AssignPhi(TNode<T> * result,Node * phi)1441   static void AssignPhi(TNode<T>* result, Node* phi) {
1442     if (phi != nullptr) *result = TNode<T>::UncheckedCast(phi);
1443   }
1444 };
1445 
1446 using CodeAssemblerExceptionHandlerLabel =
1447     CodeAssemblerParameterizedLabel<Object>;
1448 
1449 class V8_EXPORT_PRIVATE CodeAssemblerState {
1450  public:
1451   // Create with CallStub linkage.
1452   // |result_size| specifies the number of results returned by the stub.
1453   // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
1454   CodeAssemblerState(Isolate* isolate, Zone* zone,
1455                      const CallInterfaceDescriptor& descriptor, CodeKind kind,
1456                      const char* name, PoisoningMitigationLevel poisoning_level,
1457                      int32_t builtin_index = Builtins::kNoBuiltinId);
1458 
1459   // Create with JSCall linkage.
1460   CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
1461                      CodeKind kind, const char* name,
1462                      PoisoningMitigationLevel poisoning_level,
1463                      int32_t builtin_index = Builtins::kNoBuiltinId);
1464 
1465   ~CodeAssemblerState();
1466 
1467   CodeAssemblerState(const CodeAssemblerState&) = delete;
1468   CodeAssemblerState& operator=(const CodeAssemblerState&) = delete;
1469 
name()1470   const char* name() const { return name_; }
1471   int parameter_count() const;
1472 
1473 #if DEBUG
1474   void PrintCurrentBlock(std::ostream& os);
1475 #endif  // DEBUG
1476   bool InsideBlock();
1477   void SetInitialDebugInformation(const char* msg, const char* file, int line);
1478 
1479  private:
1480   friend class CodeAssembler;
1481   friend class CodeAssemblerLabel;
1482   friend class CodeAssemblerVariable;
1483   friend class CodeAssemblerTester;
1484   friend class CodeAssemblerParameterizedLabelBase;
1485   friend class ScopedExceptionHandler;
1486 
1487   CodeAssemblerState(Isolate* isolate, Zone* zone,
1488                      CallDescriptor* call_descriptor, CodeKind kind,
1489                      const char* name, PoisoningMitigationLevel poisoning_level,
1490                      int32_t builtin_index);
1491 
1492   void PushExceptionHandler(CodeAssemblerExceptionHandlerLabel* label);
1493   void PopExceptionHandler();
1494 
1495   std::unique_ptr<RawMachineAssembler> raw_assembler_;
1496   CodeKind kind_;
1497   const char* name_;
1498   int32_t builtin_index_;
1499   bool code_generated_;
1500   ZoneSet<CodeAssemblerVariable::Impl*, CodeAssemblerVariable::ImplComparator>
1501       variables_;
1502   CodeAssemblerCallback call_prologue_;
1503   CodeAssemblerCallback call_epilogue_;
1504   std::vector<CodeAssemblerExceptionHandlerLabel*> exception_handler_labels_;
1505   using VariableId = uint32_t;
1506   VariableId next_variable_id_ = 0;
1507   JSGraph* jsgraph_;
1508 
1509   // Only used by CodeStubAssembler builtins.
1510   std::vector<FileAndLine> macro_call_stack_;
1511 
NextVariableId()1512   VariableId NextVariableId() { return next_variable_id_++; }
1513 };
1514 
1515 class V8_EXPORT_PRIVATE ScopedExceptionHandler {
1516  public:
1517   ScopedExceptionHandler(CodeAssembler* assembler,
1518                          CodeAssemblerExceptionHandlerLabel* label);
1519 
1520   // Use this constructor for compatability/ports of old CSA code only. New code
1521   // should use the CodeAssemblerExceptionHandlerLabel version.
1522   ScopedExceptionHandler(CodeAssembler* assembler, CodeAssemblerLabel* label,
1523                          TypedCodeAssemblerVariable<Object>* exception);
1524 
1525   ~ScopedExceptionHandler();
1526 
1527  private:
1528   bool has_handler_;
1529   CodeAssembler* assembler_;
1530   CodeAssemblerLabel* compatibility_label_;
1531   std::unique_ptr<CodeAssemblerExceptionHandlerLabel> label_;
1532   TypedCodeAssemblerVariable<Object>* exception_;
1533 };
1534 
1535 }  // namespace compiler
1536 
1537 #if defined(V8_HOST_ARCH_32_BIT)
1538 #define BINT_IS_SMI
1539 using BInt = Smi;
1540 #elif defined(V8_HOST_ARCH_64_BIT)
1541 #define BINT_IS_INTPTR
1542 using BInt = IntPtrT;
1543 #else
1544 #error Unknown architecture.
1545 #endif
1546 
1547 }  // namespace internal
1548 }  // namespace v8
1549 
1550 #endif  // V8_COMPILER_CODE_ASSEMBLER_H_
1551