Line data Source code
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 <map>
9 : #include <memory>
10 :
11 : // Clients of this interface shouldn't depend on lots of compiler internals.
12 : // Do not include anything from src/compiler here!
13 : #include "src/allocation.h"
14 : #include "src/base/template-utils.h"
15 : #include "src/builtins/builtins.h"
16 : #include "src/code-factory.h"
17 : #include "src/globals.h"
18 : #include "src/heap/heap.h"
19 : #include "src/machine-type.h"
20 : #include "src/runtime/runtime.h"
21 : #include "src/zone/zone-containers.h"
22 :
23 : namespace v8 {
24 : namespace internal {
25 :
26 : class Callable;
27 : class CallInterfaceDescriptor;
28 : class Isolate;
29 : class Factory;
30 : class Zone;
31 :
32 : struct UntaggedT {};
33 :
34 : struct IntegralT : UntaggedT {};
35 :
36 : struct WordT : IntegralT {
37 : static const MachineRepresentation kMachineRepresentation =
38 : (kPointerSize == 4) ? MachineRepresentation::kWord32
39 : : MachineRepresentation::kWord64;
40 : };
41 :
42 : struct RawPtrT : WordT {};
43 :
44 : template <class To>
45 : struct RawPtr : RawPtrT {};
46 :
47 : struct Word32T : IntegralT {
48 : static const MachineRepresentation kMachineRepresentation =
49 : MachineRepresentation::kWord32;
50 : };
51 : struct Int32T : Word32T {
52 : static constexpr MachineType kMachineType = MachineType::Int32();
53 : };
54 : struct Uint32T : Word32T {
55 : static constexpr MachineType kMachineType = MachineType::Uint32();
56 : };
57 :
58 : struct Word64T : IntegralT {
59 : static const MachineRepresentation kMachineRepresentation =
60 : MachineRepresentation::kWord64;
61 : };
62 : struct Int64T : Word64T {
63 : static constexpr MachineType kMachineType = MachineType::Int64();
64 : };
65 : struct Uint64T : Word64T {
66 : static constexpr MachineType kMachineType = MachineType::Uint64();
67 : };
68 :
69 : struct IntPtrT : WordT {
70 : static constexpr MachineType kMachineType = MachineType::IntPtr();
71 : };
72 : struct UintPtrT : WordT {
73 : static constexpr MachineType kMachineType = MachineType::UintPtr();
74 : };
75 :
76 : struct Float32T : UntaggedT {
77 : static const MachineRepresentation kMachineRepresentation =
78 : MachineRepresentation::kFloat32;
79 : static constexpr MachineType kMachineType = MachineType::Float32();
80 : };
81 :
82 : struct Float64T : UntaggedT {
83 : static const MachineRepresentation kMachineRepresentation =
84 : MachineRepresentation::kFloat64;
85 : static constexpr MachineType kMachineType = MachineType::Float64();
86 : };
87 :
88 : // Result of a comparison operation.
89 : struct BoolT : Word32T {};
90 :
91 : // Value type of a Turbofan node with two results.
92 : template <class T1, class T2>
93 : struct PairT {};
94 :
95 : inline constexpr MachineType CommonMachineType(MachineType type1,
96 : MachineType type2) {
97 : return (type1 == type2) ? type1
98 : : ((type1.IsTagged() && type2.IsTagged())
99 : ? MachineType::AnyTagged()
100 : : MachineType::None());
101 : }
102 :
103 : template <class Type, class Enable = void>
104 : struct MachineTypeOf {
105 : static constexpr MachineType value = Type::kMachineType;
106 : };
107 :
108 : template <class Type, class Enable>
109 : constexpr MachineType MachineTypeOf<Type, Enable>::value;
110 :
111 : template <>
112 : struct MachineTypeOf<Object> {
113 : static constexpr MachineType value = MachineType::AnyTagged();
114 : };
115 : template <>
116 : struct MachineTypeOf<Smi> {
117 : static constexpr MachineType value = MachineType::TaggedSigned();
118 : };
119 : template <class HeapObjectSubtype>
120 : struct MachineTypeOf<HeapObjectSubtype,
121 : typename std::enable_if<std::is_base_of<
122 : HeapObject, HeapObjectSubtype>::value>::type> {
123 : static constexpr MachineType value = MachineType::TaggedPointer();
124 : };
125 :
126 : template <class HeapObjectSubtype>
127 : constexpr MachineType MachineTypeOf<
128 : HeapObjectSubtype, typename std::enable_if<std::is_base_of<
129 : HeapObject, HeapObjectSubtype>::value>::type>::value;
130 :
131 : template <class Type, class Enable = void>
132 : struct MachineRepresentationOf {
133 : static const MachineRepresentation value = Type::kMachineRepresentation;
134 : };
135 : template <class T>
136 : struct MachineRepresentationOf<
137 : T, typename std::enable_if<std::is_base_of<Object, T>::value>::type> {
138 : static const MachineRepresentation value =
139 : MachineTypeOf<T>::value.representation();
140 : };
141 :
142 : template <class T>
143 : struct is_valid_type_tag {
144 : static const bool value = std::is_base_of<Object, T>::value ||
145 : std::is_base_of<UntaggedT, T>::value ||
146 : std::is_same<ExternalReference, T>::value;
147 : static const bool is_tagged = std::is_base_of<Object, T>::value;
148 : };
149 :
150 : template <class T1, class T2>
151 : struct is_valid_type_tag<PairT<T1, T2>> {
152 : static const bool value =
153 : is_valid_type_tag<T1>::value && is_valid_type_tag<T2>::value;
154 : static const bool is_tagged = false;
155 : };
156 :
157 : template <class T1, class T2>
158 : struct UnionT;
159 :
160 : template <class T1, class T2>
161 : struct is_valid_type_tag<UnionT<T1, T2>> {
162 : static const bool is_tagged =
163 : is_valid_type_tag<T1>::is_tagged && is_valid_type_tag<T2>::is_tagged;
164 : static const bool value = is_tagged;
165 : };
166 :
167 : template <class T1, class T2>
168 : struct UnionT {
169 : static constexpr MachineType kMachineType =
170 : CommonMachineType(MachineTypeOf<T1>::value, MachineTypeOf<T2>::value);
171 : static const MachineRepresentation kMachineRepresentation =
172 : kMachineType.representation();
173 : static_assert(kMachineRepresentation != MachineRepresentation::kNone,
174 : "no common representation");
175 : static_assert(is_valid_type_tag<T1>::is_tagged &&
176 : is_valid_type_tag<T2>::is_tagged,
177 : "union types are only possible for tagged values");
178 : };
179 :
180 : using Number = UnionT<Smi, HeapNumber>;
181 : using Numeric = UnionT<Number, BigInt>;
182 :
183 : #define ENUM_ELEMENT(Name) k##Name,
184 : #define ENUM_STRUCT_ELEMENT(NAME, Name, name) k##Name,
185 : enum class ObjectType {
186 : kObject,
187 : OBJECT_TYPE_LIST(ENUM_ELEMENT) HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT)
188 : STRUCT_LIST(ENUM_STRUCT_ELEMENT)
189 : };
190 : #undef ENUM_ELEMENT
191 : #undef ENUM_STRUCT_ELEMENT
192 :
193 : class AccessCheckNeeded;
194 : class CompilationCacheTable;
195 : class Constructor;
196 : class Filler;
197 : class InternalizedString;
198 : class JSArgumentsObject;
199 : class JSContextExtensionObject;
200 : class JSError;
201 : class JSSloppyArgumentsObject;
202 : class MapCache;
203 : class MutableHeapNumber;
204 : class NativeContext;
205 : class SloppyArgumentsElements;
206 : class StringWrapper;
207 : class Undetectable;
208 : class UniqueName;
209 : class WasmMemoryObject;
210 : class WasmModuleObject;
211 : class WasmTableObject;
212 :
213 : template <class T>
214 : struct ObjectTypeOf {};
215 :
216 : #define OBJECT_TYPE_CASE(Name) \
217 : template <> \
218 : struct ObjectTypeOf<Name> { \
219 : static const ObjectType value = ObjectType::k##Name; \
220 : };
221 : #define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name) \
222 : template <> \
223 : struct ObjectTypeOf<Name> { \
224 : static const ObjectType value = ObjectType::k##Name; \
225 : };
226 : #define OBJECT_TYPE_TEMPLATE_CASE(Name) \
227 : template <class... Args> \
228 : struct ObjectTypeOf<Name<Args...>> { \
229 : static const ObjectType value = ObjectType::k##Name; \
230 : };
231 : OBJECT_TYPE_CASE(Object)
232 : OBJECT_TYPE_LIST(OBJECT_TYPE_CASE)
233 : HEAP_OBJECT_ORDINARY_TYPE_LIST(OBJECT_TYPE_CASE)
234 : STRUCT_LIST(OBJECT_TYPE_STRUCT_CASE)
235 : HEAP_OBJECT_TEMPLATE_TYPE_LIST(OBJECT_TYPE_TEMPLATE_CASE)
236 : #undef OBJECT_TYPE_CASE
237 : #undef OBJECT_TYPE_STRUCT_CASE
238 : #undef OBJECT_TYPE_TEMPLATE_CASE
239 :
240 : Smi* CheckObjectType(Object* value, Smi* type, String* location);
241 :
242 : namespace compiler {
243 :
244 : class CallDescriptor;
245 : class CodeAssemblerLabel;
246 : class CodeAssemblerVariable;
247 : template <class T>
248 : class TypedCodeAssemblerVariable;
249 : class CodeAssemblerState;
250 : class Node;
251 : class RawMachineAssembler;
252 : class RawMachineLabel;
253 :
254 : typedef ZoneList<CodeAssemblerVariable*> CodeAssemblerVariableList;
255 :
256 : typedef std::function<void()> CodeAssemblerCallback;
257 :
258 : template <class T, class U>
259 : struct is_subtype {
260 : static const bool value = std::is_base_of<U, T>::value;
261 : };
262 : template <class T1, class T2, class U>
263 : struct is_subtype<UnionT<T1, T2>, U> {
264 : static const bool value =
265 : is_subtype<T1, U>::value && is_subtype<T2, U>::value;
266 : };
267 : template <class T, class U1, class U2>
268 : struct is_subtype<T, UnionT<U1, U2>> {
269 : static const bool value =
270 : is_subtype<T, U1>::value || is_subtype<T, U2>::value;
271 : };
272 : template <class T1, class T2, class U1, class U2>
273 : struct is_subtype<UnionT<T1, T2>, UnionT<U1, U2>> {
274 : static const bool value =
275 : (is_subtype<T1, U1>::value || is_subtype<T1, U2>::value) &&
276 : (is_subtype<T2, U1>::value || is_subtype<T2, U2>::value);
277 : };
278 :
279 : template <class T, class U>
280 : struct types_have_common_values {
281 : static const bool value = is_subtype<T, U>::value || is_subtype<U, T>::value;
282 : };
283 : template <class U>
284 : struct types_have_common_values<Uint32T, U> {
285 : static const bool value = types_have_common_values<Word32T, U>::value;
286 : };
287 : template <class U>
288 : struct types_have_common_values<Int32T, U> {
289 : static const bool value = types_have_common_values<Word32T, U>::value;
290 : };
291 : template <class U>
292 : struct types_have_common_values<Uint64T, U> {
293 : static const bool value = types_have_common_values<Word64T, U>::value;
294 : };
295 : template <class U>
296 : struct types_have_common_values<Int64T, U> {
297 : static const bool value = types_have_common_values<Word64T, U>::value;
298 : };
299 : template <class U>
300 : struct types_have_common_values<IntPtrT, U> {
301 : static const bool value = types_have_common_values<WordT, U>::value;
302 : };
303 : template <class U>
304 : struct types_have_common_values<UintPtrT, U> {
305 : static const bool value = types_have_common_values<WordT, U>::value;
306 : };
307 : template <class T1, class T2, class U>
308 : struct types_have_common_values<UnionT<T1, T2>, U> {
309 : static const bool value = types_have_common_values<T1, U>::value ||
310 : types_have_common_values<T2, U>::value;
311 : };
312 :
313 : template <class T, class U1, class U2>
314 : struct types_have_common_values<T, UnionT<U1, U2>> {
315 : static const bool value = types_have_common_values<T, U1>::value ||
316 : types_have_common_values<T, U2>::value;
317 : };
318 : template <class T1, class T2, class U1, class U2>
319 : struct types_have_common_values<UnionT<T1, T2>, UnionT<U1, U2>> {
320 : static const bool value = types_have_common_values<T1, U1>::value ||
321 : types_have_common_values<T1, U2>::value ||
322 : types_have_common_values<T2, U1>::value ||
323 : types_have_common_values<T2, U2>::value;
324 : };
325 :
326 : // TNode<T> is an SSA value with the static type tag T, which is one of the
327 : // following:
328 : // - a subclass of internal::Object represents a tagged type
329 : // - a subclass of internal::UntaggedT represents an untagged type
330 : // - ExternalReference
331 : // - PairT<T1, T2> for an operation returning two values, with types T1
332 : // and T2
333 : // - UnionT<T1, T2> represents either a value of type T1 or of type T2.
334 : template <class T>
335 : class TNode {
336 : public:
337 : static_assert(is_valid_type_tag<T>::value, "invalid type tag");
338 :
339 : template <class U,
340 : typename std::enable_if<is_subtype<U, T>::value, int>::type = 0>
341 1847519 : TNode(const TNode<U>& other) : node_(other) {}
342 1988 : TNode() : node_(nullptr) {}
343 :
344 : TNode operator=(TNode other) {
345 : DCHECK_NULL(node_);
346 1988 : node_ = other.node_;
347 : return *this;
348 : }
349 :
350 6453494 : operator compiler::Node*() const { return node_; }
351 :
352 : static TNode UncheckedCast(compiler::Node* node) { return TNode(node); }
353 :
354 : protected:
355 2355166 : explicit TNode(compiler::Node* node) : node_(node) {}
356 :
357 : private:
358 : compiler::Node* node_;
359 : };
360 :
361 : // SloppyTNode<T> is a variant of TNode<T> and allows implicit casts from
362 : // Node*. It is intended for function arguments as long as some call sites
363 : // still use untyped Node* arguments.
364 : // TODO(tebbi): Delete this class once transition is finished.
365 : template <class T>
366 : class SloppyTNode : public TNode<T> {
367 : public:
368 : SloppyTNode(compiler::Node* node) // NOLINT(runtime/explicit)
369 : : TNode<T>(node) {}
370 : template <class U, typename std::enable_if<is_subtype<U, T>::value,
371 : int>::type = 0>
372 : SloppyTNode(const TNode<U>& other) // NOLINT(runtime/explicit)
373 515719 : : TNode<T>(other) {}
374 : };
375 :
376 : // This macro alias allows to use PairT<T1, T2> as a macro argument.
377 : #define PAIR_TYPE(T1, T2) PairT<T1, T2>
378 :
379 : #define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
380 : V(Float32Equal, BoolT, Float32T, Float32T) \
381 : V(Float32LessThan, BoolT, Float32T, Float32T) \
382 : V(Float32LessThanOrEqual, BoolT, Float32T, Float32T) \
383 : V(Float32GreaterThan, BoolT, Float32T, Float32T) \
384 : V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
385 : V(Float64Equal, BoolT, Float64T, Float64T) \
386 : V(Float64LessThan, BoolT, Float64T, Float64T) \
387 : V(Float64LessThanOrEqual, BoolT, Float64T, Float64T) \
388 : V(Float64GreaterThan, BoolT, Float64T, Float64T) \
389 : V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
390 : V(Int32GreaterThan, BoolT, Word32T, Word32T) \
391 : V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T) \
392 : V(Int32LessThan, BoolT, Word32T, Word32T) \
393 : V(Int32LessThanOrEqual, BoolT, Word32T, Word32T) \
394 : V(IntPtrLessThan, BoolT, WordT, WordT) \
395 : V(IntPtrLessThanOrEqual, BoolT, WordT, WordT) \
396 : V(IntPtrGreaterThan, BoolT, WordT, WordT) \
397 : V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT) \
398 : V(IntPtrEqual, BoolT, WordT, WordT) \
399 : V(Uint32LessThan, BoolT, Word32T, Word32T) \
400 : V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T) \
401 : V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T) \
402 : V(UintPtrLessThan, BoolT, WordT, WordT) \
403 : V(UintPtrLessThanOrEqual, BoolT, WordT, WordT) \
404 : V(UintPtrGreaterThan, BoolT, WordT, WordT) \
405 : V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT) \
406 : V(WordEqual, BoolT, WordT, WordT) \
407 : V(WordNotEqual, BoolT, WordT, WordT) \
408 : V(Word32Equal, BoolT, Word32T, Word32T) \
409 : V(Word32NotEqual, BoolT, Word32T, Word32T) \
410 : V(Word64Equal, BoolT, Word64T, Word64T) \
411 : V(Word64NotEqual, BoolT, Word64T, Word64T)
412 :
413 : #define CODE_ASSEMBLER_BINARY_OP_LIST(V) \
414 : CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
415 : V(Float64Add, Float64T, Float64T, Float64T) \
416 : V(Float64Sub, Float64T, Float64T, Float64T) \
417 : V(Float64Mul, Float64T, Float64T, Float64T) \
418 : V(Float64Div, Float64T, Float64T, Float64T) \
419 : V(Float64Mod, Float64T, Float64T, Float64T) \
420 : V(Float64Atan2, Float64T, Float64T, Float64T) \
421 : V(Float64Pow, Float64T, Float64T, Float64T) \
422 : V(Float64Max, Float64T, Float64T, Float64T) \
423 : V(Float64Min, Float64T, Float64T, Float64T) \
424 : V(Float64InsertLowWord32, Float64T, Float64T, Word32T) \
425 : V(Float64InsertHighWord32, Float64T, Float64T, Word32T) \
426 : V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
427 : V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
428 : V(Int32Add, Word32T, Word32T, Word32T) \
429 : V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
430 : V(Int32Sub, Word32T, Word32T, Word32T) \
431 : V(Int32Mul, Word32T, Word32T, Word32T) \
432 : V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
433 : V(Int32Div, Int32T, Int32T, Int32T) \
434 : V(Int32Mod, Int32T, Int32T, Int32T) \
435 : V(WordRor, WordT, WordT, IntegralT) \
436 : V(Word32Ror, Word32T, Word32T, Word32T) \
437 : V(Word64Ror, Word64T, Word64T, Word64T)
438 :
439 : TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
440 :
441 : #define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
442 : V(Float64Abs, Float64T, Float64T) \
443 : V(Float64Acos, Float64T, Float64T) \
444 : V(Float64Acosh, Float64T, Float64T) \
445 : V(Float64Asin, Float64T, Float64T) \
446 : V(Float64Asinh, Float64T, Float64T) \
447 : V(Float64Atan, Float64T, Float64T) \
448 : V(Float64Atanh, Float64T, Float64T) \
449 : V(Float64Cos, Float64T, Float64T) \
450 : V(Float64Cosh, Float64T, Float64T) \
451 : V(Float64Exp, Float64T, Float64T) \
452 : V(Float64Expm1, Float64T, Float64T) \
453 : V(Float64Log, Float64T, Float64T) \
454 : V(Float64Log1p, Float64T, Float64T) \
455 : V(Float64Log2, Float64T, Float64T) \
456 : V(Float64Log10, Float64T, Float64T) \
457 : V(Float64Cbrt, Float64T, Float64T) \
458 : V(Float64Neg, Float64T, Float64T) \
459 : V(Float64Sin, Float64T, Float64T) \
460 : V(Float64Sinh, Float64T, Float64T) \
461 : V(Float64Sqrt, Float64T, Float64T) \
462 : V(Float64Tan, Float64T, Float64T) \
463 : V(Float64Tanh, Float64T, Float64T) \
464 : V(Float64ExtractLowWord32, Word32T, Float64T) \
465 : V(Float64ExtractHighWord32, Word32T, Float64T) \
466 : V(BitcastTaggedToWord, IntPtrT, Object) \
467 : V(BitcastWordToTagged, Object, WordT) \
468 : V(BitcastWordToTaggedSigned, Smi, WordT) \
469 : V(TruncateFloat64ToFloat32, Float32T, Float64T) \
470 : V(TruncateFloat64ToWord32, Word32T, Float64T) \
471 : V(TruncateInt64ToInt32, Int32T, Int64T) \
472 : V(ChangeFloat32ToFloat64, Float64T, Float32T) \
473 : V(ChangeFloat64ToUint32, Uint32T, Float64T) \
474 : V(ChangeFloat64ToUint64, Uint64T, Float64T) \
475 : V(ChangeInt32ToFloat64, Float64T, Int32T) \
476 : V(ChangeInt32ToInt64, Int64T, Int32T) \
477 : V(ChangeUint32ToFloat64, Float64T, Word32T) \
478 : V(ChangeUint32ToUint64, Uint64T, Word32T) \
479 : V(RoundFloat64ToInt32, Int32T, Float64T) \
480 : V(RoundInt32ToFloat32, Int32T, Float32T) \
481 : V(Float64SilenceNaN, Float64T, Float64T) \
482 : V(Float64RoundDown, Float64T, Float64T) \
483 : V(Float64RoundUp, Float64T, Float64T) \
484 : V(Float64RoundTiesEven, Float64T, Float64T) \
485 : V(Float64RoundTruncate, Float64T, Float64T) \
486 : V(Word32Clz, Int32T, Word32T) \
487 : V(Word32Not, Word32T, Word32T) \
488 : V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T) \
489 : V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T) \
490 : V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
491 : V(Word32BinaryNot, Word32T, Word32T)
492 :
493 : // A "public" interface used by components outside of compiler directory to
494 : // create code objects with TurboFan's backend. This class is mostly a thin
495 : // shim around the RawMachineAssembler, and its primary job is to ensure that
496 : // the innards of the RawMachineAssembler and other compiler implementation
497 : // details don't leak outside of the the compiler directory..
498 : //
499 : // V8 components that need to generate low-level code using this interface
500 : // should include this header--and this header only--from the compiler
501 : // directory (this is actually enforced). Since all interesting data
502 : // structures are forward declared, it's not possible for clients to peek
503 : // inside the compiler internals.
504 : //
505 : // In addition to providing isolation between TurboFan and code generation
506 : // clients, CodeAssembler also provides an abstraction for creating variables
507 : // and enhanced Label functionality to merge variable values along paths where
508 : // they have differing values, including loops.
509 : //
510 : // The CodeAssembler itself is stateless (and instances are expected to be
511 : // temporary-scoped and short-lived); all its state is encapsulated into
512 : // a CodeAssemblerState instance.
513 : class V8_EXPORT_PRIVATE CodeAssembler {
514 : public:
515 58506 : explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
516 : ~CodeAssembler();
517 :
518 : static Handle<Code> GenerateCode(CodeAssemblerState* state);
519 :
520 : bool Is64() const;
521 : bool IsFloat64RoundUpSupported() const;
522 : bool IsFloat64RoundDownSupported() const;
523 : bool IsFloat64RoundTiesEvenSupported() const;
524 : bool IsFloat64RoundTruncateSupported() const;
525 : bool IsInt32AbsWithOverflowSupported() const;
526 : bool IsInt64AbsWithOverflowSupported() const;
527 : bool IsIntPtrAbsWithOverflowSupported() const;
528 :
529 : // Shortened aliases for use in CodeAssembler subclasses.
530 : using Label = CodeAssemblerLabel;
531 : using Variable = CodeAssemblerVariable;
532 : template <class T>
533 : using TVariable = TypedCodeAssemblerVariable<T>;
534 : using VariableList = CodeAssemblerVariableList;
535 :
536 : // ===========================================================================
537 : // Base Assembler
538 : // ===========================================================================
539 :
540 : template <class PreviousType>
541 : class CheckedNode {
542 : public:
543 : #ifdef DEBUG
544 : CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
545 : : node_(node), code_assembler_(code_assembler), location_(location) {}
546 : #else
547 : CheckedNode(compiler::Node* node, CodeAssembler*, const char*)
548 : : node_(node) {}
549 : #endif
550 :
551 : template <class A>
552 : operator TNode<A>() {
553 : static_assert(types_have_common_values<A, PreviousType>::value,
554 : "Incompatible types: this cast can never succeed.");
555 : static_assert(std::is_convertible<TNode<A>, TNode<Object>>::value,
556 : "Coercion to untagged values cannot be "
557 : "checked.");
558 : #ifdef DEBUG
559 : if (FLAG_debug_code) {
560 : Node* function = code_assembler_->ExternalConstant(
561 : ExternalReference::check_object_type(code_assembler_->isolate()));
562 : code_assembler_->CallCFunction3(
563 : MachineType::AnyTagged(), MachineType::AnyTagged(),
564 : MachineType::TaggedSigned(), MachineType::AnyTagged(), function,
565 : node_,
566 : code_assembler_->SmiConstant(
567 : static_cast<int>(ObjectTypeOf<A>::value)),
568 : code_assembler_->StringConstant(location_));
569 : }
570 : #endif
571 : return TNode<A>::UncheckedCast(node_);
572 : }
573 :
574 : template <class A>
575 : operator SloppyTNode<A>() {
576 : return base::implicit_cast<TNode<A>>(*this);
577 : }
578 :
579 : Node* node() const { return node_; }
580 :
581 : private:
582 : Node* node_;
583 : #ifdef DEBUG
584 : CodeAssembler* code_assembler_;
585 : const char* location_;
586 : #endif
587 : };
588 :
589 : template <class T>
590 : TNode<T> UncheckedCast(Node* value) {
591 : return TNode<T>::UncheckedCast(value);
592 : }
593 : template <class T, class U>
594 : TNode<T> UncheckedCast(TNode<U> value) {
595 : static_assert(types_have_common_values<T, U>::value,
596 : "Incompatible types: this cast can never succeed.");
597 : return TNode<T>::UncheckedCast(value);
598 : }
599 :
600 : // ReinterpretCast<T>(v) has the power to cast even when the type of v is
601 : // unrelated to T. Use with care.
602 : template <class T>
603 : TNode<T> ReinterpretCast(Node* value) {
604 : return TNode<T>::UncheckedCast(value);
605 : }
606 :
607 : CheckedNode<Object> Cast(Node* value, const char* location) {
608 : return CheckedNode<Object>(value, this, location);
609 : }
610 :
611 : template <class T>
612 : CheckedNode<T> Cast(TNode<T> value, const char* location) {
613 : return CheckedNode<T>(value, this, location);
614 : }
615 :
616 : #ifdef DEBUG
617 : #define STRINGIFY(x) #x
618 : #define TO_STRING_LITERAL(x) STRINGIFY(x)
619 : #define CAST(x) \
620 : Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
621 : #else
622 : #define CAST(x) Cast(x, "")
623 : #endif
624 :
625 : // Constants.
626 : TNode<Int32T> Int32Constant(int32_t value);
627 : TNode<Int64T> Int64Constant(int64_t value);
628 : TNode<IntPtrT> IntPtrConstant(intptr_t value);
629 : TNode<Number> NumberConstant(double value);
630 : TNode<Smi> SmiConstant(Smi* value);
631 : TNode<Smi> SmiConstant(int value);
632 : TNode<HeapObject> UntypedHeapConstant(Handle<HeapObject> object);
633 : template <class Type>
634 : TNode<Type> HeapConstant(Handle<Type> object) {
635 59283 : return UncheckedCast<Type>(UntypedHeapConstant(object));
636 : }
637 : TNode<String> StringConstant(const char* str);
638 : TNode<Oddball> BooleanConstant(bool value);
639 : TNode<ExternalReference> ExternalConstant(ExternalReference address);
640 : TNode<Float64T> Float64Constant(double value);
641 : TNode<HeapNumber> NaNConstant();
642 :
643 : bool ToInt32Constant(Node* node, int32_t& out_value);
644 : bool ToInt64Constant(Node* node, int64_t& out_value);
645 : bool ToSmiConstant(Node* node, Smi*& out_value);
646 : bool ToIntPtrConstant(Node* node, intptr_t& out_value);
647 :
648 : TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
649 : TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
650 : TNode<Uint32T> Unsigned(TNode<Word32T> x) {
651 : return UncheckedCast<Uint32T>(x);
652 : }
653 : TNode<UintPtrT> Unsigned(TNode<WordT> x) {
654 : return UncheckedCast<UintPtrT>(x);
655 : }
656 :
657 : Node* Parameter(int value);
658 :
659 : TNode<Context> GetJSContextParameter();
660 : void Return(SloppyTNode<Object> value);
661 : void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2);
662 : void Return(SloppyTNode<Object> value1, SloppyTNode<Object> value2,
663 : SloppyTNode<Object> value3);
664 : void PopAndReturn(Node* pop, Node* value);
665 :
666 : void ReturnIf(Node* condition, Node* value);
667 :
668 : void DebugAbort(Node* message);
669 : void DebugBreak();
670 : void Unreachable();
671 : void Comment(const char* format, ...);
672 :
673 : void Bind(Label* label);
674 : #if DEBUG
675 : void Bind(Label* label, AssemblerDebugInfo debug_info);
676 : #endif // DEBUG
677 : void Goto(Label* label);
678 : void GotoIf(SloppyTNode<IntegralT> condition, Label* true_label);
679 : void GotoIfNot(SloppyTNode<IntegralT> condition, Label* false_label);
680 : void Branch(SloppyTNode<IntegralT> condition, Label* true_label,
681 : Label* false_label);
682 :
683 : void Switch(Node* index, Label* default_label, const int32_t* case_values,
684 : Label** case_labels, size_t case_count);
685 :
686 : // Access to the frame pointer
687 : Node* LoadFramePointer();
688 : Node* LoadParentFramePointer();
689 :
690 : // Access to the stack pointer
691 : Node* LoadStackPointer();
692 :
693 : // Load raw memory location.
694 : Node* Load(MachineType rep, Node* base);
695 : template <class Type>
696 : TNode<Type> Load(MachineType rep, TNode<RawPtr<Type>> base) {
697 : DCHECK(
698 : IsSubtype(rep.representation(), MachineRepresentationOf<Type>::value));
699 2573 : return UncheckedCast<Type>(Load(rep, static_cast<Node*>(base)));
700 : }
701 : Node* Load(MachineType rep, Node* base, Node* offset);
702 : Node* AtomicLoad(MachineType rep, Node* base, Node* offset);
703 :
704 : // Load a value from the root array.
705 : TNode<Object> LoadRoot(Heap::RootListIndex root_index);
706 :
707 : // Store value to raw memory location.
708 : Node* Store(Node* base, Node* value);
709 : Node* Store(Node* base, Node* offset, Node* value);
710 : Node* StoreWithMapWriteBarrier(Node* base, Node* offset, Node* value);
711 : Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
712 : Node* StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
713 : Node* value);
714 : Node* AtomicStore(MachineRepresentation rep, Node* base, Node* offset,
715 : Node* value);
716 :
717 : // Exchange value at raw memory location
718 : Node* AtomicExchange(MachineType type, Node* base, Node* offset, Node* value);
719 :
720 : // Compare and Exchange value at raw memory location
721 : Node* AtomicCompareExchange(MachineType type, Node* base, Node* offset,
722 : Node* old_value, Node* new_value);
723 :
724 : Node* AtomicAdd(MachineType type, Node* base, Node* offset, Node* value);
725 :
726 : Node* AtomicSub(MachineType type, Node* base, Node* offset, Node* value);
727 :
728 : Node* AtomicAnd(MachineType type, Node* base, Node* offset, Node* value);
729 :
730 : Node* AtomicOr(MachineType type, Node* base, Node* offset, Node* value);
731 :
732 : Node* AtomicXor(MachineType type, Node* base, Node* offset, Node* value);
733 :
734 : // Store a value to the root array.
735 : Node* StoreRoot(Heap::RootListIndex root_index, Node* value);
736 :
737 : // Basic arithmetic operations.
738 : #define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
739 : TNode<ResType> name(SloppyTNode<Arg1Type> a, SloppyTNode<Arg2Type> b);
740 : CODE_ASSEMBLER_BINARY_OP_LIST(DECLARE_CODE_ASSEMBLER_BINARY_OP)
741 : #undef DECLARE_CODE_ASSEMBLER_BINARY_OP
742 :
743 : TNode<IntPtrT> WordShr(TNode<IntPtrT> left, TNode<IntegralT> right) {
744 : return UncheckedCast<IntPtrT>(
745 471 : WordShr(static_cast<Node*>(left), static_cast<Node*>(right)));
746 : }
747 :
748 : TNode<IntPtrT> WordAnd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
749 : return UncheckedCast<IntPtrT>(
750 76939 : WordAnd(static_cast<Node*>(left), static_cast<Node*>(right)));
751 : }
752 :
753 : template <class Left, class Right,
754 : class = typename std::enable_if<
755 : std::is_base_of<Object, Left>::value &&
756 : std::is_base_of<Object, Right>::value>::type>
757 : TNode<BoolT> WordEqual(TNode<Left> left, TNode<Right> right) {
758 : return WordEqual(ReinterpretCast<WordT>(left),
759 72658 : ReinterpretCast<WordT>(right));
760 : }
761 : TNode<BoolT> WordEqual(TNode<Object> left, Node* right) {
762 : return WordEqual(ReinterpretCast<WordT>(left),
763 1643 : ReinterpretCast<WordT>(right));
764 : }
765 : TNode<BoolT> WordEqual(Node* left, TNode<Object> right) {
766 : return WordEqual(ReinterpretCast<WordT>(left),
767 21662 : ReinterpretCast<WordT>(right));
768 : }
769 : template <class Left, class Right,
770 : class = typename std::enable_if<
771 : std::is_base_of<Object, Left>::value &&
772 : std::is_base_of<Object, Right>::value>::type>
773 : TNode<BoolT> WordNotEqual(TNode<Left> left, TNode<Right> right) {
774 : return WordNotEqual(ReinterpretCast<WordT>(left),
775 1469 : ReinterpretCast<WordT>(right));
776 : }
777 : TNode<BoolT> WordNotEqual(TNode<Object> left, Node* right) {
778 : return WordNotEqual(ReinterpretCast<WordT>(left),
779 : ReinterpretCast<WordT>(right));
780 : }
781 : TNode<BoolT> WordNotEqual(Node* left, TNode<Object> right) {
782 : return WordNotEqual(ReinterpretCast<WordT>(left),
783 2449 : ReinterpretCast<WordT>(right));
784 : }
785 :
786 : TNode<Int32T> Int32Add(TNode<Int32T> left, TNode<Int32T> right) {
787 : return Signed(
788 6 : Int32Add(static_cast<Node*>(left), static_cast<Node*>(right)));
789 : }
790 :
791 : TNode<WordT> IntPtrAdd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
792 : TNode<WordT> IntPtrSub(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
793 : TNode<WordT> IntPtrMul(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
794 : TNode<IntPtrT> IntPtrAdd(TNode<IntPtrT> left, TNode<IntPtrT> right) {
795 : return Signed(
796 9486 : IntPtrAdd(static_cast<Node*>(left), static_cast<Node*>(right)));
797 : }
798 : TNode<IntPtrT> IntPtrSub(TNode<IntPtrT> left, TNode<IntPtrT> right) {
799 : return Signed(
800 7101 : IntPtrSub(static_cast<Node*>(left), static_cast<Node*>(right)));
801 : }
802 : TNode<IntPtrT> IntPtrMul(TNode<IntPtrT> left, TNode<IntPtrT> right) {
803 : return Signed(
804 : IntPtrMul(static_cast<Node*>(left), static_cast<Node*>(right)));
805 : }
806 :
807 : TNode<WordT> WordShl(SloppyTNode<WordT> value, int shift);
808 : TNode<WordT> WordShr(SloppyTNode<WordT> value, int shift);
809 : TNode<IntPtrT> WordShr(TNode<IntPtrT> value, int shift) {
810 1184 : return UncheckedCast<IntPtrT>(WordShr(static_cast<Node*>(value), shift));
811 : }
812 : TNode<Word32T> Word32Shr(SloppyTNode<Word32T> value, int shift);
813 :
814 : TNode<WordT> WordOr(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
815 : TNode<WordT> WordAnd(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
816 : TNode<WordT> WordXor(SloppyTNode<WordT> left, SloppyTNode<WordT> right);
817 : TNode<WordT> WordShl(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
818 : TNode<WordT> WordShr(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
819 : TNode<WordT> WordSar(SloppyTNode<WordT> left, SloppyTNode<IntegralT> right);
820 : TNode<Word32T> Word32Or(SloppyTNode<Word32T> left,
821 : SloppyTNode<Word32T> right);
822 : TNode<Word32T> Word32And(SloppyTNode<Word32T> left,
823 : SloppyTNode<Word32T> right);
824 : TNode<Word32T> Word32Xor(SloppyTNode<Word32T> left,
825 : SloppyTNode<Word32T> right);
826 : TNode<Word32T> Word32Shl(SloppyTNode<Word32T> left,
827 : SloppyTNode<Word32T> right);
828 : TNode<Word32T> Word32Shr(SloppyTNode<Word32T> left,
829 : SloppyTNode<Word32T> right);
830 : TNode<Word32T> Word32Sar(SloppyTNode<Word32T> left,
831 : SloppyTNode<Word32T> right);
832 : TNode<Word64T> Word64Or(SloppyTNode<Word64T> left,
833 : SloppyTNode<Word64T> right);
834 : TNode<Word64T> Word64And(SloppyTNode<Word64T> left,
835 : SloppyTNode<Word64T> right);
836 : TNode<Word64T> Word64Xor(SloppyTNode<Word64T> left,
837 : SloppyTNode<Word64T> right);
838 : TNode<Word64T> Word64Shl(SloppyTNode<Word64T> left,
839 : SloppyTNode<Word64T> right);
840 : TNode<Word64T> Word64Shr(SloppyTNode<Word64T> left,
841 : SloppyTNode<Word64T> right);
842 : TNode<Word64T> Word64Sar(SloppyTNode<Word64T> left,
843 : SloppyTNode<Word64T> right);
844 :
845 : // Unary
846 : #define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
847 : TNode<ResType> name(SloppyTNode<ArgType> a);
848 : CODE_ASSEMBLER_UNARY_OP_LIST(DECLARE_CODE_ASSEMBLER_UNARY_OP)
849 : #undef DECLARE_CODE_ASSEMBLER_UNARY_OP
850 :
851 : // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
852 : // Assumes that the double can be exactly represented as an int.
853 : TNode<UintPtrT> ChangeFloat64ToUintPtr(SloppyTNode<Float64T> value);
854 :
855 : // Changes an intptr_t to a double, e.g. for storing an element index
856 : // outside Smi range in a HeapNumber. Lossless on 32-bit,
857 : // rounds on 64-bit (which doesn't affect valid element indices).
858 : Node* RoundIntPtrToFloat64(Node* value);
859 : // No-op on 32-bit, otherwise zero extend.
860 : TNode<UintPtrT> ChangeUint32ToWord(SloppyTNode<Word32T> value);
861 : // No-op on 32-bit, otherwise sign extend.
862 : TNode<IntPtrT> ChangeInt32ToIntPtr(SloppyTNode<Word32T> value);
863 :
864 : // No-op that guarantees that the value is kept alive till this point even
865 : // if GC happens.
866 : Node* Retain(Node* value);
867 :
868 : // Projections
869 : Node* Projection(int index, Node* value);
870 :
871 : template <int index, class T1, class T2>
872 : TNode<typename std::tuple_element<index, std::tuple<T1, T2>>::type>
873 : Projection(TNode<PairT<T1, T2>> value) {
874 : return UncheckedCast<
875 : typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
876 0 : Projection(index, value));
877 : }
878 :
879 : // Calls
880 : template <class... TArgs>
881 : TNode<Object> CallRuntimeImpl(Runtime::FunctionId function,
882 : SloppyTNode<Object> context, TArgs... args);
883 : template <class... TArgs>
884 93 : TNode<Object> CallRuntime(Runtime::FunctionId function,
885 : SloppyTNode<Object> context, TArgs... args) {
886 : return CallRuntimeImpl(function, context,
887 76193 : base::implicit_cast<SloppyTNode<Object>>(args)...);
888 : }
889 :
890 : template <class... TArgs>
891 : TNode<Object> TailCallRuntimeImpl(Runtime::FunctionId function,
892 : SloppyTNode<Object> context, TArgs... args);
893 : template <class... TArgs>
894 880 : TNode<Object> TailCallRuntime(Runtime::FunctionId function,
895 : SloppyTNode<Object> context, TArgs... args) {
896 : return TailCallRuntimeImpl(
897 9408 : function, context, base::implicit_cast<SloppyTNode<Object>>(args)...);
898 : }
899 :
900 : template <class... TArgs>
901 43162 : Node* CallStub(Callable const& callable, Node* context, TArgs... args) {
902 : Node* target = HeapConstant(callable.code());
903 : return CallStub(callable.descriptor(), target, context,
904 43162 : base::implicit_cast<Node*>(args)...);
905 : }
906 :
907 : template <class... TArgs>
908 : Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
909 : Node* context, TArgs... args) {
910 : return CallStubR(descriptor, 1, target, context,
911 44743 : base::implicit_cast<Node*>(args)...);
912 : }
913 :
914 : template <class... TArgs>
915 : Node* CallStubR(const CallInterfaceDescriptor& descriptor, size_t result_size,
916 : Node* target, Node* context, TArgs... args);
917 :
918 : Node* CallStubN(const CallInterfaceDescriptor& descriptor, size_t result_size,
919 : int input_count, Node* const* inputs);
920 :
921 : template <class... TArgs>
922 2449 : Node* TailCallStub(Callable const& callable, Node* context, TArgs... args) {
923 : Node* target = HeapConstant(callable.code());
924 2449 : return TailCallStub(callable.descriptor(), target, context, args...);
925 : }
926 :
927 : template <class... TArgs>
928 : Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
929 : Node* context, TArgs... args) {
930 : return TailCallStubImpl(descriptor, target, context,
931 2883 : base::implicit_cast<Node*>(args)...);
932 : }
933 : template <class... TArgs>
934 : Node* TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
935 : Node* target, Node* context, TArgs... args);
936 :
937 : template <class... TArgs>
938 : Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
939 : Node* target, TArgs... args);
940 :
941 : template <class... TArgs>
942 : Node* TailCallStubThenBytecodeDispatch(
943 : const CallInterfaceDescriptor& descriptor, Node* context, Node* target,
944 : TArgs... args);
945 :
946 : template <class... TArgs>
947 9541 : Node* CallJS(Callable const& callable, Node* context, Node* function,
948 : Node* receiver, TArgs... args) {
949 : int argc = static_cast<int>(sizeof...(args));
950 19082 : Node* arity = Int32Constant(argc);
951 9541 : return CallStub(callable, context, function, arity, receiver, args...);
952 : }
953 :
954 : template <class... TArgs>
955 322 : Node* ConstructJS(Callable const& callable, Node* context, Node* new_target,
956 : TArgs... args) {
957 : int argc = static_cast<int>(sizeof...(args));
958 644 : Node* arity = Int32Constant(argc);
959 644 : Node* receiver = LoadRoot(Heap::kUndefinedValueRootIndex);
960 :
961 : // Construct(target, new_target, arity, receiver, arguments...)
962 : return CallStub(callable, context, new_target, new_target, arity, receiver,
963 322 : args...);
964 : }
965 :
966 : Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
967 : Node* const* inputs);
968 :
969 : // Call to a C function with one argument.
970 : Node* CallCFunction1(MachineType return_type, MachineType arg0_type,
971 : Node* function, Node* arg0);
972 :
973 : // Call to a C function with one argument, while saving/restoring caller
974 : // registers except the register used for return value.
975 : Node* CallCFunction1WithCallerSavedRegisters(MachineType return_type,
976 : MachineType arg0_type,
977 : Node* function, Node* arg0,
978 : SaveFPRegsMode mode);
979 :
980 : // Call to a C function with two arguments.
981 : Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
982 : MachineType arg1_type, Node* function, Node* arg0,
983 : Node* arg1);
984 :
985 : // Call to a C function with three arguments.
986 : Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
987 : MachineType arg1_type, MachineType arg2_type,
988 : Node* function, Node* arg0, Node* arg1, Node* arg2);
989 :
990 : // Call to a C function with three arguments, while saving/restoring caller
991 : // registers except the register used for return value.
992 : Node* CallCFunction3WithCallerSavedRegisters(
993 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
994 : MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
995 : SaveFPRegsMode mode);
996 :
997 : // Call to a C function with six arguments.
998 : Node* CallCFunction6(MachineType return_type, MachineType arg0_type,
999 : MachineType arg1_type, MachineType arg2_type,
1000 : MachineType arg3_type, MachineType arg4_type,
1001 : MachineType arg5_type, Node* function, Node* arg0,
1002 : Node* arg1, Node* arg2, Node* arg3, Node* arg4,
1003 : Node* arg5);
1004 :
1005 : // Call to a C function with nine arguments.
1006 : Node* CallCFunction9(MachineType return_type, MachineType arg0_type,
1007 : MachineType arg1_type, MachineType arg2_type,
1008 : MachineType arg3_type, MachineType arg4_type,
1009 : MachineType arg5_type, MachineType arg6_type,
1010 : MachineType arg7_type, MachineType arg8_type,
1011 : Node* function, Node* arg0, Node* arg1, Node* arg2,
1012 : Node* arg3, Node* arg4, Node* arg5, Node* arg6,
1013 : Node* arg7, Node* arg8);
1014 :
1015 : // Exception handling support.
1016 : void GotoIfException(Node* node, Label* if_exception,
1017 : Variable* exception_var = nullptr);
1018 :
1019 : // Helpers which delegate to RawMachineAssembler.
1020 : Factory* factory() const;
1021 : Isolate* isolate() const;
1022 : Zone* zone() const;
1023 :
1024 1434632 : CodeAssemblerState* state() { return state_; }
1025 :
1026 : void BreakOnNode(int node_id);
1027 :
1028 : bool UnalignedLoadSupported(MachineRepresentation rep) const;
1029 : bool UnalignedStoreSupported(MachineRepresentation rep) const;
1030 :
1031 : protected:
1032 : void RegisterCallGenerationCallbacks(
1033 : const CodeAssemblerCallback& call_prologue,
1034 : const CodeAssemblerCallback& call_epilogue);
1035 : void UnregisterCallGenerationCallbacks();
1036 :
1037 : private:
1038 : RawMachineAssembler* raw_assembler() const;
1039 :
1040 : // Calls respective callback registered in the state.
1041 : void CallPrologue();
1042 : void CallEpilogue();
1043 :
1044 : CodeAssemblerState* state_;
1045 :
1046 : DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
1047 : };
1048 :
1049 : class CodeAssemblerVariable {
1050 : public:
1051 : explicit CodeAssemblerVariable(CodeAssembler* assembler,
1052 : MachineRepresentation rep);
1053 : CodeAssemblerVariable(CodeAssembler* assembler, MachineRepresentation rep,
1054 : Node* initial_value);
1055 : #if DEBUG
1056 : CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1057 : MachineRepresentation rep);
1058 : CodeAssemblerVariable(CodeAssembler* assembler, AssemblerDebugInfo debug_info,
1059 : MachineRepresentation rep, Node* initial_value);
1060 : #endif // DEBUG
1061 :
1062 : ~CodeAssemblerVariable();
1063 : void Bind(Node* value);
1064 : Node* value() const;
1065 : MachineRepresentation rep() const;
1066 : bool IsBound() const;
1067 :
1068 : private:
1069 : class Impl;
1070 : friend class CodeAssemblerLabel;
1071 : friend class CodeAssemblerState;
1072 : friend std::ostream& operator<<(std::ostream&, const Impl&);
1073 : friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1074 : Impl* impl_;
1075 : CodeAssemblerState* state_;
1076 : DISALLOW_COPY_AND_ASSIGN(CodeAssemblerVariable);
1077 : };
1078 :
1079 : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1080 : std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
1081 :
1082 : template <class T>
1083 7155 : class TypedCodeAssemblerVariable : public CodeAssemblerVariable {
1084 : public:
1085 : TypedCodeAssemblerVariable(TNode<T> initial_value, CodeAssembler* assembler)
1086 : : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value,
1087 1178 : initial_value) {}
1088 : explicit TypedCodeAssemblerVariable(CodeAssembler* assembler)
1089 5977 : : CodeAssemblerVariable(assembler, MachineRepresentationOf<T>::value) {}
1090 : #if DEBUG
1091 : TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1092 : CodeAssembler* assembler)
1093 : : CodeAssemblerVariable(assembler, debug_info,
1094 : MachineRepresentationOf<T>::value) {}
1095 : TypedCodeAssemblerVariable(AssemblerDebugInfo debug_info,
1096 : TNode<T> initial_value, CodeAssembler* assembler)
1097 : : CodeAssemblerVariable(assembler, debug_info,
1098 : MachineRepresentationOf<T>::value,
1099 : initial_value) {}
1100 : #endif // DEBUG
1101 :
1102 : template <class U, class = typename std::enable_if<
1103 : std::is_convertible<TNode<T>, TNode<U>>::value>::type>
1104 : operator TNode<U>() const {
1105 7356 : return TNode<T>::UncheckedCast(value());
1106 : }
1107 : template <class U, class = typename std::enable_if<
1108 : std::is_convertible<TNode<T>, TNode<U>>::value>::type>
1109 : operator SloppyTNode<U>() const {
1110 372 : return value();
1111 : }
1112 1395 : operator Node*() const { return value(); }
1113 :
1114 16176 : void operator=(TNode<T> value) { Bind(value); }
1115 :
1116 : private:
1117 : using CodeAssemblerVariable::Bind;
1118 : using CodeAssemblerVariable::value;
1119 : };
1120 :
1121 8928 : class CodeAssemblerLabel {
1122 : public:
1123 : enum Type { kDeferred, kNonDeferred };
1124 :
1125 : explicit CodeAssemblerLabel(
1126 : CodeAssembler* assembler,
1127 : CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1128 654174 : : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
1129 : CodeAssemblerLabel(
1130 : CodeAssembler* assembler,
1131 21066 : const CodeAssemblerVariableList& merged_variables,
1132 : CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1133 : : CodeAssemblerLabel(assembler, merged_variables.length(),
1134 21066 : &(merged_variables[0]), type) {}
1135 : CodeAssemblerLabel(
1136 : CodeAssembler* assembler, size_t count,
1137 : CodeAssemblerVariable* const* vars,
1138 : CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
1139 : CodeAssemblerLabel(
1140 : CodeAssembler* assembler,
1141 : std::initializer_list<CodeAssemblerVariable*> vars,
1142 : CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1143 5626 : : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
1144 : CodeAssemblerLabel(
1145 : CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
1146 : CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1147 65717 : : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
1148 : ~CodeAssemblerLabel();
1149 :
1150 : inline bool is_bound() const { return bound_; }
1151 :
1152 : private:
1153 : friend class CodeAssembler;
1154 :
1155 : void Bind();
1156 : #if DEBUG
1157 : void Bind(AssemblerDebugInfo debug_info);
1158 : #endif // DEBUG
1159 : void UpdateVariablesAfterBind();
1160 : void MergeVariables();
1161 :
1162 : bool bound_;
1163 : size_t merge_count_;
1164 : CodeAssemblerState* state_;
1165 : RawMachineLabel* label_;
1166 : // Map of variables that need to be merged to their phi nodes (or placeholders
1167 : // for those phis).
1168 : std::map<CodeAssemblerVariable::Impl*, Node*> variable_phis_;
1169 : // Map of variables to the list of value nodes that have been added from each
1170 : // merge path in their order of merging.
1171 : std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>> variable_merges_;
1172 : };
1173 :
1174 : class V8_EXPORT_PRIVATE CodeAssemblerState {
1175 : public:
1176 : // Create with CallStub linkage.
1177 : // |result_size| specifies the number of results returned by the stub.
1178 : // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
1179 : CodeAssemblerState(Isolate* isolate, Zone* zone,
1180 : const CallInterfaceDescriptor& descriptor, Code::Kind kind,
1181 : const char* name, size_t result_size = 1);
1182 :
1183 : // Create with JSCall linkage.
1184 : CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
1185 : Code::Kind kind, const char* name);
1186 :
1187 : ~CodeAssemblerState();
1188 :
1189 : const char* name() const { return name_; }
1190 : int parameter_count() const;
1191 :
1192 : #if DEBUG
1193 : void PrintCurrentBlock(std::ostream& os);
1194 : #endif // DEBUG
1195 : void SetInitialDebugInformation(const char* msg, const char* file, int line);
1196 :
1197 : private:
1198 : friend class CodeAssembler;
1199 : friend class CodeAssemblerLabel;
1200 : friend class CodeAssemblerVariable;
1201 : friend class CodeAssemblerTester;
1202 :
1203 : CodeAssemblerState(Isolate* isolate, Zone* zone,
1204 : CallDescriptor* call_descriptor, Code::Kind kind,
1205 : const char* name);
1206 :
1207 : std::unique_ptr<RawMachineAssembler> raw_assembler_;
1208 : Code::Kind kind_;
1209 : const char* name_;
1210 : bool code_generated_;
1211 : ZoneSet<CodeAssemblerVariable::Impl*> variables_;
1212 : CodeAssemblerCallback call_prologue_;
1213 : CodeAssemblerCallback call_epilogue_;
1214 :
1215 : DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
1216 : };
1217 :
1218 : } // namespace compiler
1219 : } // namespace internal
1220 : } // namespace v8
1221 :
1222 : #endif // V8_COMPILER_CODE_ASSEMBLER_H_
|