v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
code-assembler.h
Go to the documentation of this file.
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 <optional>
12#include <sstream>
13#include <type_traits>
14
15// Clients of this interface shouldn't depend on lots of compiler internals.
16// Do not include anything from src/compiler here!
18#include "src/base/macros.h"
25#include "src/codegen/tnode.h"
26#include "src/heap/heap.h"
28#include "src/objects/objects.h"
29#include "src/runtime/runtime.h"
31
32#if V8_ENABLE_WEBASSEMBLY
34#endif
35
36namespace v8 {
37namespace internal {
38
39// Forward declarations.
40class AsmWasmData;
41class AsyncGeneratorRequest;
42struct AssemblerOptions;
43class BigInt;
44class CallInterfaceDescriptor;
45class Callable;
46class Factory;
47class InterpreterData;
48class Isolate;
49class JSAsyncFunctionObject;
50class JSAsyncGeneratorObject;
51class JSCollator;
52class JSCollection;
53class JSDateTimeFormat;
54class JSDisplayNames;
55class JSDurationFormat;
56class JSListFormat;
57class JSLocale;
58class JSNumberFormat;
59class JSPluralRules;
60class JSRegExpStringIterator;
61class JSRelativeTimeFormat;
62class JSSegmentIterator;
63class JSSegmenter;
64class JSSegments;
65class JSV8BreakIterator;
66class JSWeakCollection;
67class JSFinalizationRegistry;
68class JSWeakMap;
69class JSWeakRef;
70class JSWeakSet;
71class OSROptimizedCodeCache;
72class ProfileDataFromFile;
73class PromiseCapability;
74class PromiseFulfillReactionJobTask;
75class PromiseReaction;
76class PromiseReactionJobTask;
77class PromiseRejectReactionJobTask;
78class TurbofanCompilationJob;
79class Zone;
80#define MAKE_FORWARD_DECLARATION(Name) class Name;
81TORQUE_DEFINED_CLASS_LIST(MAKE_FORWARD_DECLARATION)
82#undef MAKE_FORWARD_DECLARATION
83
84template <typename T>
85class Signature;
86
88inline bool NeedsBoundsCheck(CheckBounds check_bounds) {
89 switch (check_bounds) {
91 return true;
93 return DEBUG_BOOL;
94 }
95}
96
98
99template <class T>
100struct ObjectTypeOf {};
101
102#define OBJECT_TYPE_CASE(Name) \
103 template <> \
104 struct ObjectTypeOf<Name> { \
105 static constexpr ObjectType value = ObjectType::k##Name; \
106 };
107#define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name) \
108 template <> \
109 struct ObjectTypeOf<Name> { \
110 static constexpr ObjectType value = ObjectType::k##Name; \
111 };
112#define OBJECT_TYPE_TEMPLATE_CASE(Name) \
113 template <class... Args> \
114 struct ObjectTypeOf<Name<Args...>> { \
115 static constexpr ObjectType value = ObjectType::k##Name; \
116 };
117#define OBJECT_TYPE_ODDBALL_CASE(Name) \
118 template <> \
119 struct ObjectTypeOf<Name> { \
120 static constexpr ObjectType value = ObjectType::kOddball; \
121 };
122OBJECT_TYPE_CASE(Object)
124OBJECT_TYPE_CASE(TaggedIndex)
125OBJECT_TYPE_CASE(HeapObject)
137#undef OBJECT_TYPE_CASE
138#undef OBJECT_TYPE_STRUCT_CASE
139#undef OBJECT_TYPE_TEMPLATE_CASE
140
141template <class... T>
142struct ObjectTypeOf<Union<T...>> {
143 // For simplicity, don't implement TaggedIndex or HeapObjectReference.
144 static_assert(!base::has_type_v<TaggedIndex, T...>);
145 static_assert(!base::has_type_v<HeapObjectReference, T...>);
146
147 static constexpr bool kHasSmi = base::has_type_v<Smi, T...>;
148 static constexpr bool kHasObject = base::has_type_v<Object, T...>;
149 static constexpr ObjectType value =
150 (kHasSmi || kHasObject) ? ObjectType::kObject : ObjectType::kHeapObject;
151};
152
153#if defined(V8_HOST_ARCH_32_BIT)
154#define BINT_IS_SMI
155using BInt = Smi;
156using AtomicInt64 = PairT<IntPtrT, IntPtrT>;
157using AtomicUint64 = PairT<UintPtrT, UintPtrT>;
158#elif defined(V8_HOST_ARCH_64_BIT)
159#define BINT_IS_INTPTR
160using BInt = IntPtrT;
161using AtomicInt64 = IntPtrT;
162using AtomicUint64 = UintPtrT;
163#else
164#error Unknown architecture.
165#endif
166
167namespace compiler {
168
169class CallDescriptor;
170class CodeAssemblerLabel;
171class CodeAssemblerVariable;
172template <class T>
173class TypedCodeAssemblerVariable;
175class JSGraph;
176class Node;
177class RawMachineAssembler;
178class RawMachineLabel;
180
182
183using CodeAssemblerCallback = std::function<void()>;
184
185template <class... Types>
187
188// This macro alias allows to use PairT<T1, T2> as a macro argument.
189#define PAIR_TYPE(T1, T2) PairT<T1, T2>
190
191#define CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
192 V(Float32Equal, BoolT, Float32T, Float32T) \
193 V(Float32LessThan, BoolT, Float32T, Float32T) \
194 V(Float32LessThanOrEqual, BoolT, Float32T, Float32T) \
195 V(Float32GreaterThan, BoolT, Float32T, Float32T) \
196 V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
197 V(Float64Equal, BoolT, Float64T, Float64T) \
198 V(Float64NotEqual, BoolT, Float64T, Float64T) \
199 V(Float64LessThan, BoolT, Float64T, Float64T) \
200 V(Float64LessThanOrEqual, BoolT, Float64T, Float64T) \
201 V(Float64GreaterThan, BoolT, Float64T, Float64T) \
202 V(Float64GreaterThanOrEqual, BoolT, Float64T, Float64T) \
203 /* Use Word32Equal if you need Int32Equal */ \
204 V(Int32GreaterThan, BoolT, Word32T, Word32T) \
205 V(Int32GreaterThanOrEqual, BoolT, Word32T, Word32T) \
206 V(Int32LessThan, BoolT, Word32T, Word32T) \
207 V(Int32LessThanOrEqual, BoolT, Word32T, Word32T) \
208 /* Use WordEqual if you need IntPtrEqual */ \
209 V(IntPtrLessThan, BoolT, WordT, WordT) \
210 V(IntPtrLessThanOrEqual, BoolT, WordT, WordT) \
211 V(IntPtrGreaterThan, BoolT, WordT, WordT) \
212 V(IntPtrGreaterThanOrEqual, BoolT, WordT, WordT) \
213 /* Use Word32Equal if you need Uint32Equal */ \
214 V(Uint32LessThan, BoolT, Word32T, Word32T) \
215 V(Uint32LessThanOrEqual, BoolT, Word32T, Word32T) \
216 V(Uint32GreaterThan, BoolT, Word32T, Word32T) \
217 V(Uint32GreaterThanOrEqual, BoolT, Word32T, Word32T) \
218 /* Use Word64Equal if you need Uint64Equal */ \
219 V(Uint64LessThan, BoolT, Word64T, Word64T) \
220 V(Uint64LessThanOrEqual, BoolT, Word64T, Word64T) \
221 V(Uint64GreaterThan, BoolT, Word64T, Word64T) \
222 V(Uint64GreaterThanOrEqual, BoolT, Word64T, Word64T) \
223 /* Use WordEqual if you need UintPtrEqual */ \
224 V(UintPtrLessThan, BoolT, WordT, WordT) \
225 V(UintPtrLessThanOrEqual, BoolT, WordT, WordT) \
226 V(UintPtrGreaterThan, BoolT, WordT, WordT) \
227 V(UintPtrGreaterThanOrEqual, BoolT, WordT, WordT)
228
229#define CODE_ASSEMBLER_BINARY_OP_LIST(V) \
230 CODE_ASSEMBLER_COMPARE_BINARY_OP_LIST(V) \
231 V(Float32Sub, Float32T, Float32T, Float32T) \
232 V(Float32Add, Float32T, Float32T, Float32T) \
233 V(Float32Mul, Float32T, Float32T, Float32T) \
234 V(Float64Add, Float64T, Float64T, Float64T) \
235 V(Float64Sub, Float64T, Float64T, Float64T) \
236 V(Float64Mul, Float64T, Float64T, Float64T) \
237 V(Float64Div, Float64T, Float64T, Float64T) \
238 V(Float64Mod, Float64T, Float64T, Float64T) \
239 V(Float64Atan2, Float64T, Float64T, Float64T) \
240 V(Float64Pow, Float64T, Float64T, Float64T) \
241 V(Float64Max, Float64T, Float64T, Float64T) \
242 V(Float64Min, Float64T, Float64T, Float64T) \
243 V(Float64InsertLowWord32, Float64T, Float64T, Word32T) \
244 V(Float64InsertHighWord32, Float64T, Float64T, Word32T) \
245 V(I8x16Eq, I8x16T, I8x16T, I8x16T) \
246 V(IntPtrAdd, WordT, WordT, WordT) \
247 V(IntPtrSub, WordT, WordT, WordT) \
248 V(IntPtrMul, WordT, WordT, WordT) \
249 V(IntPtrMulHigh, IntPtrT, IntPtrT, IntPtrT) \
250 V(UintPtrMulHigh, UintPtrT, UintPtrT, UintPtrT) \
251 V(IntPtrDiv, IntPtrT, IntPtrT, IntPtrT) \
252 V(IntPtrMod, IntPtrT, IntPtrT, IntPtrT) \
253 V(IntPtrAddWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
254 V(IntPtrSubWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
255 V(IntPtrMulWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT, IntPtrT) \
256 V(Int32Add, Word32T, Word32T, Word32T) \
257 V(Int32AddWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
258 V(Int32Sub, Word32T, Word32T, Word32T) \
259 V(Int32SubWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
260 V(Int32Mul, Word32T, Word32T, Word32T) \
261 V(Int32MulWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T, Int32T) \
262 V(Int32Div, Int32T, Int32T, Int32T) \
263 V(Uint32Div, Uint32T, Uint32T, Uint32T) \
264 V(Int32Mod, Int32T, Int32T, Int32T) \
265 V(Uint32Mod, Uint32T, Uint32T, Uint32T) \
266 V(Int64Add, Word64T, Word64T, Word64T) \
267 V(Int64Sub, Word64T, Word64T, Word64T) \
268 V(Int64SubWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T, Int64T) \
269 V(Int64Mul, Word64T, Word64T, Word64T) \
270 V(Int64MulHigh, Int64T, Int64T, Int64T) \
271 V(Uint64MulHigh, Uint64T, Uint64T, Uint64T) \
272 V(Int64Div, Int64T, Int64T, Int64T) \
273 V(Int64Mod, Int64T, Int64T, Int64T) \
274 V(WordOr, WordT, WordT, WordT) \
275 V(WordAnd, WordT, WordT, WordT) \
276 V(WordXor, WordT, WordT, WordT) \
277 V(WordRor, WordT, WordT, IntegralT) \
278 V(WordShl, WordT, WordT, IntegralT) \
279 V(WordShr, WordT, WordT, IntegralT) \
280 V(WordSar, WordT, WordT, IntegralT) \
281 V(WordSarShiftOutZeros, WordT, WordT, IntegralT) \
282 V(Word32Or, Word32T, Word32T, Word32T) \
283 V(Word32And, Word32T, Word32T, Word32T) \
284 V(Word32Xor, Word32T, Word32T, Word32T) \
285 V(Word32Ror, Word32T, Word32T, Word32T) \
286 V(Word32Shl, Word32T, Word32T, Word32T) \
287 V(Word32Shr, Word32T, Word32T, Word32T) \
288 V(Word32Sar, Word32T, Word32T, Word32T) \
289 V(Word32SarShiftOutZeros, Word32T, Word32T, Word32T) \
290 V(Word64And, Word64T, Word64T, Word64T) \
291 V(Word64Or, Word64T, Word64T, Word64T) \
292 V(Word64Xor, Word64T, Word64T, Word64T) \
293 V(Word64Shl, Word64T, Word64T, Word64T) \
294 V(Word64Shr, Word64T, Word64T, Word64T) \
295 V(Word64Sar, Word64T, Word64T, Word64T)
296
298
299#define CODE_ASSEMBLER_UNARY_OP_LIST(V) \
300 V(Float32Abs, Float32T, Float32T) \
301 V(Float64Abs, Float64T, Float64T) \
302 V(Float64Acos, Float64T, Float64T) \
303 V(Float64Acosh, Float64T, Float64T) \
304 V(Float64Asin, Float64T, Float64T) \
305 V(Float64Asinh, Float64T, Float64T) \
306 V(Float64Atan, Float64T, Float64T) \
307 V(Float64Atanh, Float64T, Float64T) \
308 V(Float64Cos, Float64T, Float64T) \
309 V(Float64Cosh, Float64T, Float64T) \
310 V(Float64Exp, Float64T, Float64T) \
311 V(Float64Expm1, Float64T, Float64T) \
312 V(Float64Log, Float64T, Float64T) \
313 V(Float64Log1p, Float64T, Float64T) \
314 V(Float64Log2, Float64T, Float64T) \
315 V(Float64Log10, Float64T, Float64T) \
316 V(Float64Cbrt, Float64T, Float64T) \
317 V(Float64Neg, Float64T, Float64T) \
318 V(Float64Sin, Float64T, Float64T) \
319 V(Float64Sinh, Float64T, Float64T) \
320 V(Float64Sqrt, Float64T, Float64T) \
321 V(Float64Tan, Float64T, Float64T) \
322 V(Float64Tanh, Float64T, Float64T) \
323 V(Float64ExtractLowWord32, Uint32T, Float64T) \
324 V(Float64ExtractHighWord32, Uint32T, Float64T) \
325 V(BitcastTaggedToWord, IntPtrT, Object) \
326 V(BitcastTaggedToWordForTagAndSmiBits, IntPtrT, AnyTaggedT) \
327 V(BitcastMaybeObjectToWord, IntPtrT, MaybeObject) \
328 V(BitcastWordToTagged, Object, WordT) \
329 V(BitcastWordToTaggedSigned, Smi, WordT) \
330 V(TruncateFloat64ToFloat32, Float32T, Float64T) \
331 V(TruncateFloat64ToFloat16RawBits, Float16RawBitsT, Float64T) \
332 V(TruncateFloat64ToWord32, Uint32T, Float64T) \
333 V(TruncateInt64ToInt32, Int32T, Int64T) \
334 V(ChangeFloat32ToFloat64, Float64T, Float32T) \
335 V(ChangeFloat64ToUint32, Uint32T, Float64T) \
336 V(ChangeFloat64ToUint64, Uint64T, Float64T) \
337 V(ChangeFloat64ToInt64, Int64T, Float64T) \
338 V(ChangeInt32ToFloat64, Float64T, Int32T) \
339 V(ChangeInt32ToInt64, Int64T, Int32T) \
340 V(ChangeUint32ToFloat64, Float64T, Word32T) \
341 V(ChangeUint32ToUint64, Uint64T, Word32T) \
342 V(ChangeInt64ToFloat64, Float64T, Int64T) \
343 V(BitcastInt32ToFloat32, Float32T, Word32T) \
344 V(BitcastFloat32ToInt32, Uint32T, Float32T) \
345 V(BitcastFloat64ToInt64, Int64T, Float64T) \
346 V(BitcastInt64ToFloat64, Float64T, Int64T) \
347 V(RoundFloat64ToInt32, Int32T, Float64T) \
348 V(RoundInt32ToFloat32, Float32T, Int32T) \
349 V(Float64SilenceNaN, Float64T, Float64T) \
350 V(Float64RoundDown, Float64T, Float64T) \
351 V(Float64RoundUp, Float64T, Float64T) \
352 V(Float64RoundTiesEven, Float64T, Float64T) \
353 V(Float64RoundTruncate, Float64T, Float64T) \
354 V(Word32Clz, Int32T, Word32T) \
355 V(Word64Clz, Int64T, Word64T) \
356 V(Word32Ctz, Int32T, Word32T) \
357 V(Word64Ctz, Int64T, Word64T) \
358 V(Word32Popcnt, Int32T, Word32T) \
359 V(Word64Popcnt, Int64T, Word64T) \
360 V(Word32BitwiseNot, Word32T, Word32T) \
361 V(WordNot, WordT, WordT) \
362 V(Word64Not, Word64T, Word64T) \
363 V(I8x16BitMask, Int32T, I8x16T) \
364 V(I8x16Splat, I8x16T, Int32T) \
365 V(Int32AbsWithOverflow, PAIR_TYPE(Int32T, BoolT), Int32T) \
366 V(Int64AbsWithOverflow, PAIR_TYPE(Int64T, BoolT), Int64T) \
367 V(IntPtrAbsWithOverflow, PAIR_TYPE(IntPtrT, BoolT), IntPtrT) \
368 V(Word32BinaryNot, BoolT, Word32T) \
369 V(StackPointerGreaterThan, BoolT, WordT)
370
371// A "public" interface used by components outside of compiler directory to
372// create code objects with TurboFan's backend. This class is mostly a thin
373// shim around the RawMachineAssembler, and its primary job is to ensure that
374// the innards of the RawMachineAssembler and other compiler implementation
375// details don't leak outside of the the compiler directory..
376//
377// V8 components that need to generate low-level code using this interface
378// should include this header--and this header only--from the compiler
379// directory (this is actually enforced). Since all interesting data
380// structures are forward declared, it's not possible for clients to peek
381// inside the compiler internals.
382//
383// In addition to providing isolation between TurboFan and code generation
384// clients, CodeAssembler also provides an abstraction for creating variables
385// and enhanced Label functionality to merge variable values along paths where
386// they have differing values, including loops.
387//
388// The CodeAssembler itself is stateless (and instances are expected to be
389// temporary-scoped and short-lived); all its state is encapsulated into
390// a CodeAssemblerState instance.
392 public:
393 explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
395
396 CodeAssembler(const CodeAssembler&) = delete;
398
399 bool Is64() const;
400 bool Is32() const;
401 bool IsFloat64RoundUpSupported() const;
402 bool IsFloat64RoundDownSupported() const;
403 bool IsFloat64RoundTiesEvenSupported() const;
404 bool IsFloat64RoundTruncateSupported() const;
405 bool IsTruncateFloat64ToFloat16RawBitsSupported() const;
406 bool IsInt32AbsWithOverflowSupported() const;
407 bool IsInt64AbsWithOverflowSupported() const;
408 bool IsIntPtrAbsWithOverflowSupported() const;
409 bool IsWord32PopcntSupported() const;
410 bool IsWord64PopcntSupported() const;
411 bool IsWord32CtzSupported() const;
412 bool IsWord64CtzSupported() const;
413
414 // A scheduler to ensure deterministic builtin compilation regardless of
415 // v8_flags.concurrent_builtin_generation.
416 //
417 // Builtin jobs are compiled in three (3) stages: PrepareJob, ExecuteJob, and
418 // FinalizeJob.
419 //
420 // PrepareJob and FinalizeJob may allocate on the heap and must run on the
421 // main thread. ExecuteJob only allocates in the job's Zone and may run on a
422 // helper thread. To ensure deterministic builds, there must be a total order
423 // of all heap allocations across all spaces. In other words, there must be a
424 // single total order of PrepareJob and FinalizeJob calls.
425 //
426 // This order is enforced by batching according to zone size. For each batch,
427 //
428 // 1. In ascending order of job->FinalizeOrder(), call PrepareJob for each
429 // job.
430 // 2. Call ExecuteJob for each job in the batch in any order, possibly in
431 // parallel.
432 // 3. In ascending order of job->FinalizeOrder(), call FinalizeJob for each
433 // job.
434 //
435 // Example use:
436 //
437 // BuiltinCompilationScheduler scheduler;
438 // scheduler.CompileCode(job1);
439 // scheduler.CompileCode(job2);
440 // scheduler.AwaitAndFinalizeCurrentBatch();
442 public:
444
445 int builtins_installed_count() const { return builtins_installed_count_; }
446
447 void CompileCode(Isolate* isolate,
448 std::unique_ptr<TurbofanCompilationJob> job);
449
450 void AwaitAndFinalizeCurrentBatch(Isolate* isolate);
451
452 private:
453 void QueueJob(Isolate* isolate,
454 std::unique_ptr<TurbofanCompilationJob> job);
455
456 void FinalizeJobOnMainThread(Isolate* isolate, TurbofanCompilationJob* job);
457
458 int builtins_installed_count_ = 0;
459
460 // The sum of the size of Zones of all queued jobs.
461 size_t current_batch_zone_size_ = 0;
462
463 // Only used when !v8_flags.concurrent_builtin_generation. Used to keep the
464 // allocation order identical between generating builtins concurrently and
465 // non-concurrently for reproducible builds.
466 std::deque<std::unique_ptr<TurbofanCompilationJob>>
468 };
469
470 // Shortened aliases for use in CodeAssembler subclasses.
472 template <class T>
475
476 // ===========================================================================
477 // Base Assembler
478 // ===========================================================================
479
480 template <class PreviousType, bool FromTyped>
482 public:
483#ifdef DEBUG
484 CheckedNode(Node* node, CodeAssembler* code_assembler, const char* location)
485 : node_(node), code_assembler_(code_assembler), location_(location) {}
486#else
488 : node_(node) {}
489#endif
490
491 template <class A>
492 operator TNode<A>() {
493 static_assert(!std::is_same<A, Tagged<MaybeObject>>::value,
494 "Can't cast to Tagged<MaybeObject>, use explicit "
495 "conversion functions. ");
496
498 "Incompatible types: this cast can never succeed.");
499 static_assert(std::is_convertible<TNode<A>, TNode<MaybeObject>>::value ||
500 std::is_convertible<TNode<A>, TNode<Object>>::value,
501 "Coercion to untagged values cannot be "
502 "checked.");
503 static_assert(
504 !FromTyped ||
505 !std::is_convertible<TNode<PreviousType>, TNode<A>>::value,
506 "Unnecessary CAST: types are convertible.");
507#ifdef DEBUG
508 if (v8_flags.slow_debug_code) {
509 TNode<ExternalReference> function = code_assembler_->ExternalConstant(
510 ExternalReference::check_object_type());
511 code_assembler_->CallCFunction(
512 function, MachineType::AnyTagged(),
513 std::make_pair(MachineType::AnyTagged(), node_),
514 std::make_pair(MachineType::TaggedSigned(),
515 code_assembler_->SmiConstant(
516 static_cast<int>(ObjectTypeOf<A>::value))),
517 std::make_pair(MachineType::AnyTagged(),
518 code_assembler_->StringConstant(location_)));
519 }
520#endif
522 }
523
524 Node* node() const { return node_; }
525
526 private:
528#ifdef DEBUG
529 CodeAssembler* code_assembler_;
530 const char* location_;
531#endif
532 };
533
534 template <class T>
536 return TNode<T>::UncheckedCast(value);
537 }
538 template <class T, class U>
541 "Incompatible types: this cast can never succeed.");
542 return TNode<T>::UncheckedCast(value);
543 }
544
545 // ReinterpretCast<T>(v) has the power to cast even when the type of v is
546 // unrelated to T. Use with care.
547 template <class T>
549 return TNode<T>::UncheckedCast(value);
550 }
551
552 CheckedNode<Object, false> Cast(Node* value, const char* location = "") {
553 return {value, this, location};
554 }
555
556 template <class T>
557 CheckedNode<T, true> Cast(TNode<T> value, const char* location = "") {
558 return {value, this, location};
559 }
560
561#ifdef DEBUG
562#define STRINGIFY(x) #x
563#define TO_STRING_LITERAL(x) STRINGIFY(x)
564#define CAST(x) \
565 Cast(x, "CAST(" #x ") at " __FILE__ ":" TO_STRING_LITERAL(__LINE__))
566#define TORQUE_CAST(...) \
567 ca_.Cast(__VA_ARGS__, "CAST(" #__VA_ARGS__ ") at " __FILE__ \
568 ":" TO_STRING_LITERAL(__LINE__))
569#else
570#define CAST(x) Cast(x)
571#define TORQUE_CAST(...) ca_.Cast(__VA_ARGS__)
572#endif
573
574 // Constants.
575 TNode<Int32T> UniqueInt32Constant(int32_t value);
576 TNode<Int32T> Int32Constant(int32_t value);
577 TNode<Int64T> UniqueInt64Constant(int64_t value);
578 TNode<Int64T> Int64Constant(int64_t value);
580 return Unsigned(Int64Constant(base::bit_cast<int64_t>(value)));
581 }
582 TNode<IntPtrT> IntPtrConstant(intptr_t value);
583 TNode<IntPtrT> UniqueIntPtrConstant(intptr_t value);
585 return Unsigned(UniqueInt32Constant(base::bit_cast<int32_t>(value)));
586 }
588 return Unsigned(Int32Constant(base::bit_cast<int32_t>(value)));
589 }
591 return Uint32Constant(value >> 32);
592 }
594 DCHECK_EQ(0, value & ~uint32_t{0});
595 return Uint64HighWordConstant(value);
596 }
598 return Uint32Constant(static_cast<uint32_t>(value));
599 }
601 return Unsigned(IntPtrConstant(base::bit_cast<intptr_t>(value)));
602 }
603 TNode<TaggedIndex> TaggedIndexConstant(intptr_t value);
605 return ReinterpretCast<RawPtrT>(
606 IntPtrConstant(reinterpret_cast<intptr_t>(value)));
607 }
608 TNode<Number> NumberConstant(double value);
609 TNode<Smi> SmiConstant(Tagged<Smi> value);
610 TNode<Smi> SmiConstant(int value);
611 template <typename E>
613 requires std::is_enum<E>::value
614 {
615 static_assert(sizeof(E) <= sizeof(int));
616 return SmiConstant(static_cast<int>(value));
617 }
618
619 void CanonicalizeEmbeddedBuiltinsConstantIfNeeded(Handle<HeapObject> object);
620 TNode<HeapObject> UntypedHeapConstantNoHole(Handle<HeapObject> object);
621 TNode<HeapObject> UntypedHeapConstantMaybeHole(Handle<HeapObject> object);
622 TNode<HeapObject> UntypedHeapConstantHole(Handle<HeapObject> object);
623 template <class Type>
625 return UncheckedCast<Type>(UntypedHeapConstantNoHole(object));
626 }
627 template <class Type>
629 return UncheckedCast<Type>(UntypedHeapConstantMaybeHole(object));
630 }
631 template <class Type>
633 return UncheckedCast<Type>(UntypedHeapConstantHole(object));
634 }
635 TNode<String> StringConstant(const char* str);
636 TNode<Boolean> BooleanConstant(bool value);
637 TNode<ExternalReference> ExternalConstant(ExternalReference address);
639 TNode<Float32T> Float32Constant(double value);
640 TNode<Float64T> Float64Constant(double value);
642 return ReinterpretCast<BoolT>(Int32Constant(1));
643 }
645 return ReinterpretCast<BoolT>(Int32Constant(0));
646 }
648 return value ? Int32TrueConstant() : Int32FalseConstant();
649 }
651 return ReinterpretCast<ExternalPointerHandleT>(Uint32Constant(0));
652 }
653
654 bool IsMapOffsetConstant(Node* node);
655
656 bool TryToInt32Constant(TNode<IntegralT> node, int32_t* out_value);
657 bool TryToInt64Constant(TNode<IntegralT> node, int64_t* out_value);
658 bool TryToIntPtrConstant(TNode<IntegralT> node, intptr_t* out_value);
659 bool TryToIntPtrConstant(TNode<Smi> tnode, intptr_t* out_value);
660 bool TryToSmiConstant(TNode<IntegralT> node, Tagged<Smi>* out_value);
661 bool TryToSmiConstant(TNode<Smi> node, Tagged<Smi>* out_value);
662
663 bool IsUndefinedConstant(TNode<Object> node);
664 bool IsNullConstant(TNode<Object> node);
665
666 TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
667 TNode<Int64T> Signed(TNode<Word64T> x) { return UncheckedCast<Int64T>(x); }
668 TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
670 return UncheckedCast<Uint32T>(x);
671 }
673 return UncheckedCast<Uint64T>(x);
674 }
676 return UncheckedCast<UintPtrT>(x);
677 }
678
679 // Support for code with a "dynamic" parameter count.
680 //
681 // Code assembled by our code assembler always has a "static" parameter count
682 // as defined by the call descriptor for the code. This parameter count is
683 // known at compile time. However, some builtins also have a "dynamic"
684 // parameter count because they can be installed on different function
685 // objects with different parameter counts. In that case, the actual
686 // parameter count is only known at runtime. Examples of such builtins
687 // include the CompileLazy builtin and the InterpreterEntryTrampoline, or the
688 // generic JSToWasm and JSToJS wrappers. These builtins then may have to
689 // obtain the "dynamic" parameter count, for example to correctly remove all
690 // function arguments (including padding arguments) from the stack.
691 bool HasDynamicJSParameterCount();
692 TNode<Uint16T> DynamicJSParameterCount();
693 void SetDynamicJSParameterCount(TNode<Uint16T> parameter_count);
694
695 static constexpr int kTargetParameterIndex = kJSCallClosureParameterIndex;
696 static_assert(kTargetParameterIndex == -1);
697
698 template <class T>
700 const SourceLocation& loc = SourceLocation::Current()) {
701 static_assert(
702 std::is_convertible<TNode<T>, TNode<Object>>::value,
703 "Parameter is only for tagged types. Use UncheckedParameter instead.");
704 std::stringstream message;
705 message << "Parameter " << value;
706 if (loc.FileName()) {
707 message << " at " << loc.FileName() << ":" << loc.Line();
708 }
709 size_t buf_size = message.str().size() + 1;
710 char* message_dup = zone()->AllocateArray<char>(buf_size);
711 snprintf(message_dup, buf_size, "%s", message.str().c_str());
712
713 return Cast(UntypedParameter(value), message_dup);
714 }
715
716 template <class T>
718 return UncheckedCast<T>(UntypedParameter(value));
719 }
720
721 Node* UntypedParameter(int value);
722
723 TNode<Context> GetJSContextParameter();
724 void Return(TNode<Object> value);
725 void Return(TNode<Object> value1, TNode<Object> value2);
726 void Return(TNode<Object> value1, TNode<Object> value2, TNode<Object> value3);
727 void Return(TNode<Int32T> value);
728 void Return(TNode<Uint32T> value);
729 void Return(TNode<WordT> value);
730 void Return(TNode<Float32T> value);
731 void Return(TNode<Float64T> value);
732 void Return(TNode<WordT> value1, TNode<WordT> value2);
733 void Return(TNode<Word32T> value1, TNode<Word32T> value2);
734 void Return(TNode<WordT> value1, TNode<Object> value2);
735 void Return(TNode<Word32T> value1, TNode<Object> value2);
736 void PopAndReturn(Node* pop, Node* value);
737 void PopAndReturn(Node* pop, Node* value1, Node* value2, Node* value3,
738 Node* value4);
739
740 void ReturnIf(TNode<BoolT> condition, TNode<Object> value);
741
742 void AbortCSADcheck(Node* message);
743 void DebugBreak();
744 void Unreachable();
745
746 // Hack for supporting SourceLocation alongside template packs.
748 const char* message;
750
751 // Allow implicit construction, necessary for the hack.
752 // NOLINTNEXTLINE
754 const char* message,
755 const SourceLocation& loc = SourceLocation::Current())
756 : message(message), loc(loc) {}
757 };
758 template <class... Args>
759 void Comment(MessageWithSourceLocation message, Args&&... args) {
760 if (!v8_flags.code_comments) return;
761 std::ostringstream s;
762 USE(s << message.message, (s << std::forward<Args>(args))...);
763 if (message.loc.FileName()) {
764 s << " - " << message.loc.ToString();
765 }
766 EmitComment(std::move(s).str());
767 }
768
769 void StaticAssert(TNode<BoolT> value,
770 const char* source = "unknown position");
771
772 // The following methods refer to source positions in CSA or Torque code
773 // compiled during mksnapshot, not JS compiled at runtime.
774 void SetSourcePosition(const char* file, int line);
775 void PushSourcePosition();
776 void PopSourcePosition();
778 public:
779 explicit SourcePositionScope(CodeAssembler* ca) : ca_(ca) {
780 ca->PushSourcePosition();
781 }
782 ~SourcePositionScope() { ca_->PopSourcePosition(); }
783
784 private:
786 };
787 const std::vector<FileAndLine>& GetMacroSourcePositionStack() const;
788
789 void Bind(Label* label);
790#if DEBUG
791 void Bind(Label* label, AssemblerDebugInfo debug_info);
792#endif // DEBUG
793 void Goto(Label* label);
794
795 void GotoIf(TNode<IntegralT> condition, Label* true_label,
796 GotoHint goto_hint = GotoHint::kNone);
797 void GotoIfNot(TNode<IntegralT> condition, Label* false_label,
798 GotoHint goto_hint = GotoHint::kNone);
799 void Branch(TNode<IntegralT> condition, Label* true_label, Label* false_label,
800 BranchHint branch_hint = BranchHint::kNone);
801
802 template <class T>
804 return {};
805 }
806
807 template <class... T>
809 Bind(label->plain_label());
810 label->CreatePhis(phis...);
811 }
812 template <class... T, class... Args>
815 CodeAssemblerParameterizedLabel<T...>* if_false, Args... args) {
816 if_true->AddInputs(args...);
817 if_false->AddInputs(args...);
818 Branch(condition, if_true->plain_label(), if_false->plain_label());
819 }
820 template <class... T, class... U>
823 std::vector<Node*> args_true,
825 std::vector<Node*> args_false) {
826 if_true->AddInputsVector(std::move(args_true));
827 if_false->AddInputsVector(std::move(args_false));
828 Branch(condition, if_true->plain_label(), if_false->plain_label());
829 }
830
831 template <class... T, class... Args>
833 label->AddInputs(args...);
834 Goto(label->plain_label());
835 }
836
837 void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
838 const std::function<void()>& false_body);
839 void Branch(TNode<BoolT> condition, Label* true_label,
840 const std::function<void()>& false_body);
841 void Branch(TNode<BoolT> condition, const std::function<void()>& true_body,
842 Label* false_label);
843
844 void Switch(Node* index, Label* default_label, const int32_t* case_values,
845 Label** case_labels, size_t case_count);
846
847 // Access to the frame pointer.
848 TNode<RawPtrT> LoadFramePointer();
849 TNode<RawPtrT> LoadParentFramePointer();
850 TNode<RawPtrT> StackSlotPtr(int size, int alignment);
851
852#if V8_ENABLE_WEBASSEMBLY
853 // Access to the stack pointer.
854 TNode<RawPtrT> LoadStackPointer();
855 void SetStackPointer(TNode<RawPtrT> ptr);
856#endif // V8_ENABLE_WEBASSEMBLY
857
858 TNode<RawPtrT> LoadPointerFromRootRegister(TNode<IntPtrT> offset);
859 TNode<Uint8T> LoadUint8FromRootRegister(TNode<IntPtrT> offset);
860
861 // Load raw memory location.
862 Node* Load(MachineType type, Node* base);
863 template <class Type>
865 DCHECK(
866 IsSubtype(type.representation(), MachineRepresentationOf<Type>::value));
867 return UncheckedCast<Type>(Load(type, static_cast<Node*>(base)));
868 }
870 template <class Type>
872 return UncheckedCast<Type>(Load(MachineTypeOf<Type>::value, base));
873 }
874 template <class Type>
876 return UncheckedCast<Type>(Load(MachineTypeOf<Type>::value, base, offset));
877 }
878 template <class Type>
881 return UncheckedCast<Type>(
882 AtomicLoad(MachineTypeOf<Type>::value, order, base, offset));
883 }
884 template <class Type>
887 // Load uncompressed tagged value from (most likely off JS heap) memory
888 // location.
889 TNode<Object> LoadFullTagged(Node* base);
890 TNode<Object> LoadFullTagged(Node* base, TNode<IntPtrT> offset);
891
892 Node* LoadFromObject(MachineType type, TNode<Object> object,
894 Node* LoadProtectedPointerFromObject(TNode<Object> object,
896
897#ifdef V8_MAP_PACKING
898 Node* PackMapWord(Node* value);
899#endif
900
901 // Load a value from the root array.
902 // If map packing is enabled, LoadRoot for a root map returns the unpacked map
903 // word (i.e., the map). Use LoadRootMapWord to obtain the packed map word
904 // instead.
905 TNode<Object> LoadRoot(RootIndex root_index);
906 TNode<AnyTaggedT> LoadRootMapWord(RootIndex root_index);
907
908 template <typename Type>
911 return UncheckedCast<Type>(UnalignedLoad(mt, base, offset));
912 }
913
914 // Store value to raw memory location.
915 void Store(Node* base, Node* value);
916 void Store(Node* base, Node* offset, Node* value);
917 void StoreEphemeronKey(Node* base, Node* offset, Node* value);
918 void StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* value);
919 void StoreNoWriteBarrier(MachineRepresentation rep, Node* base, Node* offset,
920 Node* value);
921 void UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
922 Node* value);
923 void UnsafeStoreNoWriteBarrier(MachineRepresentation rep, Node* base,
924 Node* offset, Node* value);
925
926 // Stores uncompressed tagged value to (most likely off JS heap) memory
927 // location without write barrier.
928 void StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base,
929 TNode<Object> tagged_value);
930 void StoreFullTaggedNoWriteBarrier(TNode<RawPtrT> base, TNode<IntPtrT> offset,
931 TNode<Object> tagged_value);
932
933 // Optimized memory operations that map to Turbofan simplified nodes.
934 TNode<HeapObject> OptimizedAllocate(TNode<IntPtrT> size,
935 AllocationType allocation);
936 void StoreToObject(MachineRepresentation rep, TNode<Object> object,
937 TNode<IntPtrT> offset, Node* value,
938 StoreToObjectWriteBarrier write_barrier);
939 void OptimizedStoreField(MachineRepresentation rep, TNode<HeapObject> object,
940 int offset, Node* value);
941 void OptimizedStoreIndirectPointerField(TNode<HeapObject> object, int offset,
942 IndirectPointerTag tag, Node* value);
943 void OptimizedStoreIndirectPointerFieldNoWriteBarrier(
945 Node* value);
946 void OptimizedStoreFieldAssertNoWriteBarrier(MachineRepresentation rep,
947 TNode<HeapObject> object,
948 int offset, Node* value);
949 void OptimizedStoreFieldUnsafeNoWriteBarrier(MachineRepresentation rep,
950 TNode<HeapObject> object,
951 int offset, Node* value);
952 void OptimizedStoreMap(TNode<HeapObject> object, TNode<Map>);
953 void AtomicStore(MachineRepresentation rep, AtomicMemoryOrder order,
955 TNode<Word32T> value);
956 // {value_high} is used for 64-bit stores on 32-bit platforms, must be
957 // nullptr in other cases.
958 void AtomicStore64(AtomicMemoryOrder order, TNode<RawPtrT> base,
960 TNode<UintPtrT> value_high);
961
964 template <class Type>
966 TNode<UintPtrT> value, TNode<UintPtrT> value_high);
967
970 template <class Type>
972 TNode<UintPtrT> value, TNode<UintPtrT> value_high);
973
976 template <class Type>
978 TNode<UintPtrT> value, TNode<UintPtrT> value_high);
979
982 template <class Type>
984 TNode<UintPtrT> value, TNode<UintPtrT> value_high);
985
988 template <class Type>
990 TNode<UintPtrT> value, TNode<UintPtrT> value_high);
991
992 // Exchange value at raw memory location
995 template <class Type>
997 TNode<UintPtrT> value,
998 TNode<UintPtrT> value_high);
999
1000 // Compare and Exchange value at raw memory location
1001 TNode<Word32T> AtomicCompareExchange(MachineType type, TNode<RawPtrT> base,
1003 TNode<Word32T> old_value,
1004 TNode<Word32T> new_value);
1005
1006 template <class Type>
1007 TNode<Type> AtomicCompareExchange64(TNode<RawPtrT> base, TNode<WordT> offset,
1008 TNode<UintPtrT> old_value,
1009 TNode<UintPtrT> new_value,
1010 TNode<UintPtrT> old_value_high,
1011 TNode<UintPtrT> new_value_high);
1012
1013 void MemoryBarrier(AtomicMemoryOrder order);
1014
1015 // Store a value to the root array.
1016 void StoreRoot(RootIndex root_index, TNode<Object> value);
1017
1018// Basic arithmetic operations.
1019#define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \
1020 TNode<ResType> name(TNode<Arg1Type> a, TNode<Arg2Type> b);
1022#undef DECLARE_CODE_ASSEMBLER_BINARY_OP
1023
1024 // Pairwise operations for 32bit.
1025 TNode<PairT<Word32T, Word32T>> Int32PairAdd(TNode<Word32T> lhs_lo_word,
1026 TNode<Word32T> lhs_hi_word,
1027 TNode<Word32T> rhs_lo_word,
1028 TNode<Word32T> rhs_hi_word);
1029 TNode<PairT<Word32T, Word32T>> Int32PairSub(TNode<Word32T> lhs_lo_word,
1030 TNode<Word32T> lhs_hi_word,
1031 TNode<Word32T> rhs_lo_word,
1032 TNode<Word32T> rhs_hi_word);
1033
1035 return Unsigned(WordShr(static_cast<TNode<WordT>>(left), right));
1036 }
1038 return Signed(WordSar(static_cast<TNode<WordT>>(left), right));
1039 }
1041 return Signed(WordShl(static_cast<TNode<WordT>>(left), right));
1042 }
1044 return Unsigned(WordShl(static_cast<TNode<WordT>>(left), right));
1045 }
1046
1048 return Signed(Word32Shl(static_cast<TNode<Word32T>>(left), right));
1049 }
1051 return Unsigned(Word32Shl(static_cast<TNode<Word32T>>(left), right));
1052 }
1054 return Unsigned(Word32Shr(static_cast<TNode<Word32T>>(left), right));
1055 }
1057 return Signed(Word32Sar(static_cast<TNode<Word32T>>(left), right));
1058 }
1059
1061 return Signed(Word64Shl(static_cast<TNode<Word64T>>(left), right));
1062 }
1064 return Unsigned(Word64Shl(static_cast<TNode<Word64T>>(left), right));
1065 }
1067 return Signed(Word64Shr(static_cast<TNode<Word64T>>(left), right));
1068 }
1070 return Unsigned(Word64Shr(static_cast<TNode<Word64T>>(left), right));
1071 }
1073 return Signed(Word64Sar(static_cast<TNode<Word64T>>(left), right));
1074 }
1075
1077 return Signed(Word64And(static_cast<TNode<Word64T>>(left), right));
1078 }
1080 return Unsigned(Word64And(static_cast<TNode<Word64T>>(left), right));
1081 }
1082
1084 return Signed(Word64Xor(static_cast<TNode<Word64T>>(left), right));
1085 }
1087 return Unsigned(Word64Xor(static_cast<TNode<Word64T>>(left), right));
1088 }
1089
1091 return Signed(Word64Not(static_cast<TNode<Word64T>>(value)));
1092 }
1094 return Unsigned(Word64Not(static_cast<TNode<Word64T>>(value)));
1095 }
1096
1098 return Signed(WordAnd(static_cast<TNode<WordT>>(left),
1099 static_cast<TNode<WordT>>(right)));
1100 }
1102 return Unsigned(WordAnd(static_cast<TNode<WordT>>(left),
1103 static_cast<TNode<WordT>>(right)));
1104 }
1105
1107 return Signed(Word32And(static_cast<TNode<Word32T>>(left),
1108 static_cast<TNode<Word32T>>(right)));
1109 }
1111 return Unsigned(Word32And(static_cast<TNode<Word32T>>(left),
1112 static_cast<TNode<Word32T>>(right)));
1113 }
1114
1116 return Signed(WordOr(static_cast<TNode<WordT>>(left),
1117 static_cast<TNode<WordT>>(right)));
1118 }
1119
1121 return Signed(Word32Or(static_cast<TNode<Word32T>>(left),
1122 static_cast<TNode<Word32T>>(right)));
1123 }
1125 return Unsigned(Word32Or(static_cast<TNode<Word32T>>(left),
1126 static_cast<TNode<Word32T>>(right)));
1127 }
1128
1136
1138 return Signed(WordNot(static_cast<TNode<WordT>>(a)));
1139 }
1141 return Signed(Word32BitwiseNot(static_cast<TNode<Word32T>>(a)));
1142 }
1144 return UncheckedCast<BoolT>(Word32Or(static_cast<TNode<Word32T>>(left),
1145 static_cast<TNode<Word32T>>(right)));
1146 }
1148 return UncheckedCast<BoolT>(Word32And(static_cast<TNode<Word32T>>(left),
1149 static_cast<TNode<Word32T>>(right)));
1150 }
1151
1153 return Signed(Int32Add(static_cast<TNode<Word32T>>(left),
1154 static_cast<TNode<Word32T>>(right)));
1155 }
1156
1158 return Unsigned(Int32Add(static_cast<TNode<Word32T>>(left),
1159 static_cast<TNode<Word32T>>(right)));
1160 }
1161
1163 return Unsigned(Int32Sub(static_cast<TNode<Word32T>>(left),
1164 static_cast<TNode<Word32T>>(right)));
1165 }
1166
1168 return Signed(Int32Sub(static_cast<TNode<Word32T>>(left),
1169 static_cast<TNode<Word32T>>(right)));
1170 }
1171
1173 return Signed(Int32Mul(static_cast<TNode<Word32T>>(left),
1174 static_cast<TNode<Word32T>>(right)));
1175 }
1176
1178 return Unsigned(Int32Mul(static_cast<TNode<Word32T>>(left),
1179 static_cast<TNode<Word32T>>(right)));
1180 }
1181
1183 return Signed(Int64Add(static_cast<TNode<Word64T>>(left), right));
1184 }
1185
1187 return Unsigned(Int64Add(static_cast<TNode<Word64T>>(left), right));
1188 }
1189
1191 return Signed(Int64Sub(static_cast<TNode<Word64T>>(left), right));
1192 }
1193
1195 return Unsigned(Int64Sub(static_cast<TNode<Word64T>>(left), right));
1196 }
1197
1199 return Signed(Int64Mul(static_cast<TNode<Word64T>>(left), right));
1200 }
1201
1203 return Unsigned(Int64Mul(static_cast<TNode<Word64T>>(left), right));
1204 }
1205
1207 return Signed(IntPtrAdd(static_cast<TNode<WordT>>(left),
1208 static_cast<TNode<WordT>>(right)));
1209 }
1211 return Signed(IntPtrSub(static_cast<TNode<WordT>>(left),
1212 static_cast<TNode<WordT>>(right)));
1213 }
1215 return Signed(IntPtrMul(static_cast<TNode<WordT>>(left),
1216 static_cast<TNode<WordT>>(right)));
1217 }
1219 return Unsigned(IntPtrAdd(static_cast<TNode<WordT>>(left),
1220 static_cast<TNode<WordT>>(right)));
1221 }
1223 return Unsigned(IntPtrSub(static_cast<TNode<WordT>>(left),
1224 static_cast<TNode<WordT>>(right)));
1225 }
1227 return ReinterpretCast<RawPtrT>(IntPtrAdd(left, right));
1228 }
1230 return ReinterpretCast<RawPtrT>(IntPtrSub(left, right));
1231 }
1233 return Signed(IntPtrSub(static_cast<TNode<WordT>>(left),
1234 static_cast<TNode<WordT>>(right)));
1235 }
1236
1237 TNode<WordT> WordShl(TNode<WordT> value, int shift);
1238 TNode<WordT> WordShr(TNode<WordT> value, int shift);
1239 TNode<WordT> WordSar(TNode<WordT> value, int shift);
1241 return UncheckedCast<IntPtrT>(WordShr(TNode<WordT>(value), shift));
1242 }
1244 return UncheckedCast<IntPtrT>(WordSar(TNode<WordT>(value), shift));
1245 }
1246 TNode<Word32T> Word32Shr(TNode<Word32T> value, int shift);
1247 TNode<Word32T> Word32Sar(TNode<Word32T> value, int shift);
1248
1249 // Convenience overloads.
1251 return Int32Sub(left, Int32Constant(right));
1252 }
1254 return Word32And(left, Int32Constant(right));
1255 }
1257 return Word32Shl(left, Int32Constant(right));
1258 }
1260 return Word32Equal(left, Int32Constant(right));
1261 }
1262
1263// Unary
1264#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \
1265 TNode<ResType> name(TNode<ArgType> a);
1267#undef DECLARE_CODE_ASSEMBLER_UNARY_OP
1268
1269 template <class Dummy = void>
1271 static_assert(sizeof(Dummy) < 0,
1272 "Should use BitcastTaggedToWordForTagAndSmiBits instead.");
1273 }
1274
1275 // Changes a double to an inptr_t for pointer arithmetic outside of Smi range.
1276 // Assumes that the double can be exactly represented as an int.
1277 TNode<IntPtrT> ChangeFloat64ToIntPtr(TNode<Float64T> value);
1278 TNode<UintPtrT> ChangeFloat64ToUintPtr(TNode<Float64T> value);
1279 // Same in the opposite direction.
1280 TNode<Float64T> ChangeUintPtrToFloat64(TNode<UintPtrT> value);
1281
1282 // Changes an intptr_t to a double, e.g. for storing an element index
1283 // outside Smi range in a HeapNumber. Lossless on 32-bit,
1284 // rounds on 64-bit (which doesn't affect valid element indices).
1285 TNode<Float64T> RoundIntPtrToFloat64(Node* value);
1286 // No-op on 32-bit, otherwise zero extend.
1287 TNode<UintPtrT> ChangeUint32ToWord(TNode<Word32T> value);
1288 // No-op on 32-bit, otherwise sign extend.
1289 TNode<IntPtrT> ChangeInt32ToIntPtr(TNode<Word32T> value);
1290
1291 // Truncates a float to a 32-bit integer. If the float is outside of 32-bit
1292 // range, make sure that overflow detection is easy. In particular, return
1293 // int_min instead of int_max on arm platforms by using parameter
1294 // kSetOverflowToMin.
1295 TNode<Int32T> TruncateFloat32ToInt32(TNode<Float32T> value);
1296 TNode<Int64T> TruncateFloat64ToInt64(TNode<Float64T> value);
1297
1298 // Projections
1299 template <int index, class T1, class T2>
1302 return UncheckedCast<
1303 typename std::tuple_element<index, std::tuple<T1, T2>>::type>(
1304 Projection(index, value));
1305 }
1306
1307 // Calls
1308 template <class T = Object, class... TArgs>
1310 TArgs... args) {
1311 return UncheckedCast<T>(CallRuntimeImpl(
1312 function, context, {implicit_cast<TNode<Object>>(args)...}));
1313 }
1314
1315 template <class... TArgs>
1317 TArgs... args) {
1318 int argc = static_cast<int>(sizeof...(args));
1319 TNode<Int32T> arity = Int32Constant(argc);
1320 return TailCallRuntimeImpl(function, arity, context,
1322 }
1323
1324 template <class... TArgs>
1326 TNode<Object> context, TArgs... args) {
1327 return TailCallRuntimeImpl(function, arity, context,
1329 }
1330
1331 Builtin builtin();
1332
1333 // If the current code is running on a secondary stack, move the stack pointer
1334 // to the central stack (but not the frame pointer) and adjust the stack
1335 // limit. Returns the old stack pointer, or nullptr if no switch was
1336 // performed.
1339 // Switch the SP back to the secondary stack after switching to the central
1340 // stack.
1342
1343 //
1344 // If context passed to CallBuiltin is nullptr, it won't be passed to the
1345 // builtin.
1346 //
1347 template <typename T = Object, class... TArgs>
1349 DCHECK_WITH_MSG(!Builtins::HasJSLinkage(id), "Use CallJSBuiltin instead");
1350 TNode<RawPtrT> old_sp;
1351#if V8_ENABLE_WEBASSEMBLY
1352 bool maybe_needs_switch = wasm::BuiltinLookup::IsWasmBuiltinId(builtin()) &&
1353 !wasm::BuiltinLookup::IsWasmBuiltinId(id);
1354 if (maybe_needs_switch) {
1355 old_sp = SwitchToTheCentralStackIfNeeded();
1356 }
1357#endif
1358 Callable callable = Builtins::CallableFor(isolate(), id);
1359 TNode<Code> target = HeapConstantNoHole(callable.code());
1360 TNode<T> call =
1361 CallStub<T>(callable.descriptor(), target, context, args...);
1362#if V8_ENABLE_WEBASSEMBLY
1363 if (maybe_needs_switch) {
1364 SwitchFromTheCentralStack(old_sp);
1365 }
1366#endif
1367 return call;
1368 }
1369
1370 template <class... TArgs>
1371 void CallBuiltinVoid(Builtin id, TNode<Object> context, TArgs... args) {
1372 DCHECK_WITH_MSG(!Builtins::HasJSLinkage(id), "Use CallJSBuiltin instead");
1373 Callable callable = Builtins::CallableFor(isolate(), id);
1374 TNode<Code> target = HeapConstantNoHole(callable.code());
1375 CallStubR(StubCallMode::kCallCodeObject, callable.descriptor(), target,
1376 context, args...);
1377 }
1378
1379 template <class... TArgs>
1380 void TailCallBuiltin(Builtin id, TNode<Object> context, TArgs... args) {
1381 DCHECK_WITH_MSG(!Builtins::HasJSLinkage(id),
1382 "Use TailCallJSBuiltin instead");
1383 Callable callable = Builtins::CallableFor(isolate(), id);
1384 TNode<Code> target = HeapConstantNoHole(callable.code());
1385 TailCallStub(callable.descriptor(), target, context, args...);
1386 }
1387
1388 //
1389 // If context passed to CallStub is nullptr, it won't be passed to the stub.
1390 //
1391
1392 template <class T = Object, class... TArgs>
1394 TNode<Code> target, TNode<Object> context, TArgs... args) {
1395 return UncheckedCast<T>(CallStubR(StubCallMode::kCallCodeObject, descriptor,
1396 target, context, args...));
1397 }
1398
1399 template <class T = Object, class... TArgs>
1401 TNode<BuiltinPtr> target, TNode<Object> context,
1402 TArgs... args) {
1403 return UncheckedCast<T>(CallStubR(StubCallMode::kCallBuiltinPointer,
1404 descriptor, target, context, args...));
1405 }
1406
1407 template <class... TArgs>
1409 TNode<Code> target, TNode<Object> context, TArgs... args) {
1410 TailCallStubImpl(descriptor, target, context, {args...});
1411 }
1412
1413 template <class... TArgs>
1414 void TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
1415 TNode<RawPtrT> target, TArgs... args);
1416
1417 template <class... TArgs>
1419 TArgs... args) {
1420 Callable callable = Builtins::CallableFor(isolate(), builtin);
1421 TNode<Code> target = HeapConstantNoHole(callable.code());
1422 TailCallStubThenBytecodeDispatchImpl(callable.descriptor(), target, context,
1423 {args...});
1424 }
1425
1426 // A specialized version of CallBuiltin for builtins with JS linkage.
1427 // This for example takes care of computing and supplying the argument count.
1428 template <class... TArgs>
1430 TNode<Object> function,
1431 std::optional<TNode<Object>> new_target,
1432 TNode<Object> receiver, TArgs... args) {
1433 DCHECK(Builtins::HasJSLinkage(builtin));
1434 // The receiver is also passed on the stack so needs to be included.
1435 DCHECK_EQ(Builtins::GetStackParameterCount(builtin), 1 + sizeof...(args));
1436 Callable callable = Builtins::CallableFor(isolate(), builtin);
1437 int argc = JSParameterCount(static_cast<int>(sizeof...(args)));
1438 TNode<Int32T> arity = Int32Constant(argc);
1439 TNode<JSDispatchHandleT> dispatch_handle = UncheckedCast<JSDispatchHandleT>(
1440 Uint32Constant(kInvalidDispatchHandle.value()));
1441 TNode<Code> target = HeapConstantNoHole(callable.code());
1442 return CAST(CallJSStubImpl(callable.descriptor(), target, context, function,
1443 new_target, arity, dispatch_handle,
1444 {receiver, args...}));
1445 }
1446
1447 // A specialized version of TailCallBuiltin for builtins with JS linkage.
1448 // The JS arguments (including receiver) must already be on the stack.
1451 TNode<Int32T> arg_count,
1452 TNode<JSDispatchHandleT> dispatch_handle) {
1453 DCHECK(Builtins::HasJSLinkage(id));
1454 Callable callable = Builtins::CallableFor(isolate(), id);
1455 TNode<Code> target = HeapConstantNoHole(callable.code());
1456#ifdef V8_JS_LINKAGE_INCLUDES_DISPATCH_HANDLE
1457 TailCallStub(callable.descriptor(), target, context, function, new_target,
1458 arg_count, dispatch_handle);
1459#else
1460 TailCallStub(callable.descriptor(), target, context, function, new_target,
1461 arg_count);
1462#endif
1463 }
1464
1465 // Call the given JavaScript callable through one of the JS Call builtins.
1466 template <class... TArgs>
1469 TArgs... args) {
1470 DCHECK(Builtins::IsAnyCall(builtin));
1471 Callable callable = Builtins::CallableFor(isolate(), builtin);
1472 int argc = JSParameterCount(static_cast<int>(sizeof...(args)));
1473 TNode<Int32T> arity = Int32Constant(argc);
1474 TNode<Code> target = HeapConstantNoHole(callable.code());
1475 return CAST(CallJSStubImpl(callable.descriptor(), target, context, function,
1476 std::nullopt, arity, std::nullopt,
1477 {receiver, args...}));
1478 }
1479
1480 // Construct the given JavaScript callable through a JS Construct builtin.
1481 template <class... TArgs>
1484 TArgs... args) {
1485 // Consider creating a Builtins::IsAnyConstruct if we ever expect other
1486 // Construct builtins here.
1487 DCHECK_EQ(builtin, Builtin::kConstruct);
1488 Callable callable = Builtins::CallableFor(isolate(), builtin);
1489 int argc = JSParameterCount(static_cast<int>(sizeof...(args)));
1490 TNode<Int32T> arity = Int32Constant(argc);
1491 TNode<JSAny> receiver = CAST(LoadRoot(RootIndex::kUndefinedValue));
1492 TNode<Code> target = HeapConstantNoHole(callable.code());
1493 return CAST(CallJSStubImpl(callable.descriptor(), target, context, function,
1494 new_target, arity, std::nullopt,
1495 {receiver, args...}));
1496 }
1497
1498 // Tailcalls to the given code object with JSCall linkage. The JS arguments
1499 // (including receiver) are supposed to be already on the stack.
1500 // This is a building block for implementing trampoline stubs that are
1501 // installed instead of code objects with JSCall linkage.
1502 // Note that no arguments adaption is going on here - all the JavaScript
1503 // arguments are left on the stack unmodified. Therefore, this tail call can
1504 // only be used after arguments adaptation has been performed already.
1505 void TailCallJSCode(TNode<Code> code, TNode<Context> context,
1507 TNode<Int32T> arg_count,
1508 TNode<JSDispatchHandleT> dispatch_handle);
1509
1510 Node* CallCFunctionN(Signature<MachineType>* signature, int input_count,
1511 Node* const* inputs);
1512
1513 // Type representing C function argument with type info.
1514 using CFunctionArg = std::pair<MachineType, Node*>;
1515
1516 // Call to a C function.
1517 template <class... CArgs>
1518 Node* CallCFunction(Node* function, std::optional<MachineType> return_type,
1519 CArgs... cargs) {
1520 static_assert(
1521 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1522 "invalid argument types");
1523 return CallCFunction(function, return_type, {cargs...});
1524 }
1525
1526 // Call to a C function without a function discriptor on AIX.
1527 template <class... CArgs>
1529 MachineType return_type,
1530 CArgs... cargs) {
1531 static_assert(
1532 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1533 "invalid argument types");
1534 return CallCFunctionWithoutFunctionDescriptor(function, return_type,
1535 {cargs...});
1536 }
1537
1538 // Call to a C function, while saving/restoring caller registers.
1539 template <class... CArgs>
1541 MachineType return_type,
1542 SaveFPRegsMode mode,
1543 CArgs... cargs) {
1544 static_assert(
1545 std::conjunction_v<std::is_convertible<CArgs, CFunctionArg>...>,
1546 "invalid argument types");
1547 return CallCFunctionWithCallerSavedRegisters(function, return_type, mode,
1548 {cargs...});
1549 }
1550
1551 // Helpers which delegate to RawMachineAssembler.
1552 Factory* factory() const;
1553 Isolate* isolate() const;
1554 Zone* zone() const;
1555
1557
1558 void BreakOnNode(int node_id);
1559
1560 bool UnalignedLoadSupported(MachineRepresentation rep) const;
1561 bool UnalignedStoreSupported(MachineRepresentation rep) const;
1562
1563 bool IsExceptionHandlerActive() const;
1564
1565 protected:
1566 void RegisterCallGenerationCallbacks(
1567 const CodeAssemblerCallback& call_prologue,
1568 const CodeAssemblerCallback& call_epilogue);
1569 void UnregisterCallGenerationCallbacks();
1570
1571 bool Word32ShiftIsSafe() const;
1572
1573 bool IsJSFunctionCall() const;
1574
1575 private:
1576 void HandleException(Node* result);
1577
1578 Node* CallCFunction(Node* function, std::optional<MachineType> return_type,
1579 std::initializer_list<CFunctionArg> args);
1580
1582 Node* function, MachineType return_type,
1583 std::initializer_list<CFunctionArg> args);
1584
1586 Node* function, MachineType return_type, SaveFPRegsMode mode,
1587 std::initializer_list<CFunctionArg> args);
1588
1589 Node* CallRuntimeImpl(Runtime::FunctionId function, TNode<Object> context,
1590 std::initializer_list<TNode<Object>> args);
1591
1592 void TailCallRuntimeImpl(Runtime::FunctionId function, TNode<Int32T> arity,
1593 TNode<Object> context,
1594 std::initializer_list<TNode<Object>> args);
1595
1596 void TailCallStubImpl(const CallInterfaceDescriptor& descriptor,
1597 TNode<Code> target, TNode<Object> context,
1598 std::initializer_list<Node*> args);
1599
1600 void TailCallStubThenBytecodeDispatchImpl(
1601 const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1602 std::initializer_list<Node*> args);
1603
1604 template <class... TArgs>
1606 const CallInterfaceDescriptor& descriptor,
1607 TNode<Object> target, TNode<Object> context, TArgs... args) {
1608 return CallStubRImpl(call_mode, descriptor, target, context, {args...});
1609 }
1610
1611 Node* CallStubRImpl(StubCallMode call_mode,
1612 const CallInterfaceDescriptor& descriptor,
1613 TNode<Object> target, TNode<Object> context,
1614 std::initializer_list<Node*> args);
1615
1616 Node* CallJSStubImpl(const CallInterfaceDescriptor& descriptor,
1617 TNode<Object> target, TNode<Object> context,
1618 TNode<Object> function,
1619 std::optional<TNode<Object>> new_target,
1620 TNode<Int32T> arity,
1621 std::optional<TNode<JSDispatchHandleT>> dispatch_handle,
1622 std::initializer_list<Node*> args);
1623
1624 Node* CallStubN(StubCallMode call_mode,
1625 const CallInterfaceDescriptor& descriptor, int input_count,
1626 Node* const* inputs);
1627
1628 Node* AtomicLoad(MachineType type, AtomicMemoryOrder order,
1630
1631 Node* UnalignedLoad(MachineType type, TNode<RawPtrT> base,
1633
1634 void EmitComment(std::string msg);
1635
1636 // These two don't have definitions and are here only for catching use cases
1637 // where the cast is not necessary.
1640
1641 Node* Projection(int index, Node* value);
1642
1643 RawMachineAssembler* raw_assembler() const;
1644 JSGraph* jsgraph() const;
1645
1646 // Calls respective callback registered in the state.
1647 void CallPrologue();
1648 void CallEpilogue();
1649
1651};
1652
1653// TODO(solanes, v8:6949): this class should be merged into
1654// TypedCodeAssemblerVariable. It's required to be separate for
1655// CodeAssemblerVariableLists.
1657 public:
1660
1661 Node* value() const;
1662 MachineRepresentation rep() const;
1663 bool IsBound() const;
1664
1665 protected:
1666 explicit CodeAssemblerVariable(CodeAssembler* assembler,
1669 Node* initial_value);
1670#if DEBUG
1674 MachineRepresentation rep, Node* initial_value);
1675#endif // DEBUG
1676
1678 void Bind(Node* value);
1679
1680 private:
1681 class Impl;
1684 friend std::ostream& operator<<(std::ostream&, const Impl&);
1685 friend std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1687 bool operator()(const CodeAssemblerVariable::Impl* a,
1688 const CodeAssemblerVariable::Impl* b) const;
1689 };
1692};
1693
1694std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable&);
1695std::ostream& operator<<(std::ostream&, const CodeAssemblerVariable::Impl&);
1696
1697template <class T>
1699 public:
1702 initial_value) {}
1705#if DEBUG
1707 CodeAssembler* assembler)
1708 : CodeAssemblerVariable(assembler, debug_info,
1711 TNode<T> initial_value, CodeAssembler* assembler)
1712 : CodeAssemblerVariable(assembler, debug_info,
1713 PhiMachineRepresentationOf<T>, initial_value) {}
1714#endif // DEBUG
1715
1719
1720 void operator=(TNode<T> value) { Bind(value); }
1722 Bind(variable.value());
1723 }
1724
1725 private:
1727};
1728
1730 public:
1732
1734 CodeAssembler* assembler,
1735 CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1736 : CodeAssemblerLabel(assembler, 0, nullptr, type) {}
1738 CodeAssembler* assembler,
1739 const CodeAssemblerVariableList& merged_variables,
1740 CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1741 : CodeAssemblerLabel(assembler, merged_variables.size(),
1742 &(merged_variables[0]), type) {}
1744 CodeAssembler* assembler, size_t count,
1745 CodeAssemblerVariable* const* vars,
1746 CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred);
1748 CodeAssembler* assembler,
1749 std::initializer_list<CodeAssemblerVariable*> vars,
1750 CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1751 : CodeAssemblerLabel(assembler, vars.size(), vars.begin(), type) {}
1753 CodeAssembler* assembler, CodeAssemblerVariable* merged_variable,
1754 CodeAssemblerLabel::Type type = CodeAssemblerLabel::kNonDeferred)
1755 : CodeAssemblerLabel(assembler, 1, &merged_variable, type) {}
1757
1758 // Cannot be copied because the destructor explicitly call the destructor of
1759 // the underlying {RawMachineLabel}, hence only one pointer can point to it.
1762
1763 inline bool is_bound() const { return bound_; }
1764 inline bool is_used() const { return merge_count_ != 0; }
1765
1766 private:
1767 friend class CodeAssembler;
1768
1769 void Bind();
1770#if DEBUG
1771 void Bind(AssemblerDebugInfo debug_info);
1772#endif // DEBUG
1773 void UpdateVariablesAfterBind();
1774 void MergeVariables();
1775
1780 // Map of variables that need to be merged to their phi nodes (or placeholders
1781 // for those phis).
1785 // Map of variables to the list of value nodes that have been added from each
1786 // merge path in their order of merging.
1787 std::map<CodeAssemblerVariable::Impl*, std::vector<Node*>,
1790};
1791
1793 public:
1794 bool is_used() const { return plain_label_.is_used(); }
1796 size_t arity,
1798 : state_(assembler->state()),
1799 phi_inputs_(arity),
1800 plain_label_(assembler, type) {}
1801
1802 protected:
1804 void AddInputs(std::vector<Node*> inputs);
1805 Node* CreatePhi(MachineRepresentation rep, const std::vector<Node*>& inputs);
1806 const std::vector<Node*>& CreatePhis(
1807 std::vector<MachineRepresentation> representations);
1808
1809 private:
1811 std::vector<std::vector<Node*>> phi_inputs_;
1812 std::vector<Node*> phi_nodes_;
1814};
1815
1816template <class... Types>
1819 public:
1820 static constexpr size_t kArity = sizeof...(Types);
1824
1825 private:
1826 friend class CodeAssembler;
1827
1828 void AddInputsVector(std::vector<Node*> inputs) {
1830 }
1831 void AddInputs(TNode<Types>... inputs) {
1833 std::vector<Node*>{inputs...});
1834 }
1835 void CreatePhis(TNode<Types>*... results) {
1836 const std::vector<Node*>& phi_nodes =
1839 auto it = phi_nodes.begin();
1840 USE(it);
1841 (AssignPhi(results, *(it++)), ...);
1842 }
1843 template <class T>
1844 static void AssignPhi(TNode<T>* result, Node* phi) {
1845 if (phi != nullptr) *result = TNode<T>::UncheckedCast(phi);
1846 }
1847};
1848
1851
1853 public:
1854 // Create with CallStub linkage.
1855 // |result_size| specifies the number of results returned by the stub.
1856 // TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
1857 CodeAssemblerState(Isolate* isolate, Zone* zone,
1858 const CallInterfaceDescriptor& descriptor, CodeKind kind,
1859 const char* name, Builtin builtin = Builtin::kNoBuiltinId);
1860
1862
1865
1866 const char* name() const { return name_; }
1867 int parameter_count() const;
1868
1869#if DEBUG
1870 void PrintCurrentBlock(std::ostream& os);
1871#endif // DEBUG
1872 bool InsideBlock();
1873 void SetInitialDebugInformation(const char* msg, const char* file, int line);
1874
1875 private:
1876 friend class CodeAssembler;
1879 friend class CodeAssemblerTester;
1883
1884 CodeAssemblerState(Isolate* isolate, Zone* zone,
1885 CallDescriptor* call_descriptor, CodeKind kind,
1886 const char* name, Builtin builtin);
1887
1888 void PushExceptionHandler(CodeAssemblerExceptionHandlerLabel* label);
1889 void PopExceptionHandler();
1890
1891 std::unique_ptr<RawMachineAssembler> raw_assembler_;
1893 const char* name_;
1900 std::vector<CodeAssemblerExceptionHandlerLabel*> exception_handler_labels_;
1901 using VariableId = uint32_t;
1902 VariableId next_variable_id_ = 0;
1904
1905 // Only used by CodeStubAssembler builtins.
1906 std::vector<FileAndLine> macro_call_stack_;
1907
1908 VariableId NextVariableId() { return next_variable_id_++; }
1909};
1910
1912 public:
1915
1916 // Use this constructor for compatability/ports of old CSA code only. New code
1917 // should use the CodeAssemblerExceptionHandlerLabel version.
1920
1922
1923 private:
1927 std::unique_ptr<CodeAssemblerExceptionHandlerLabel> label_;
1929};
1930
1931} // namespace compiler
1932} // namespace internal
1933} // namespace v8
1934
1935#endif // V8_COMPILER_CODE_ASSEMBLER_H_
JSGraph * jsgraph
friend Zone
Definition asm-types.cc:195
#define T
int16_t parameter_count
Definition builtins.cc:67
Builtins::Kind kind
Definition builtins.cc:40
constexpr UnderlyingType & value() &
Handle< Code > code() const
Definition callable.h:22
CallInterfaceDescriptor descriptor() const
Definition callable.h:23
static TNode UncheckedCast(compiler::Node *node)
Definition tnode.h:413
CodeAssemblerLabel & operator=(const CodeAssemblerLabel &)=delete
std::map< CodeAssemblerVariable::Impl *, std::vector< Node * >, CodeAssemblerVariable::ImplComparator > variable_merges_
CodeAssemblerLabel(CodeAssembler *assembler, std::initializer_list< CodeAssemblerVariable * > vars, CodeAssemblerLabel::Type type=CodeAssemblerLabel::kNonDeferred)
CodeAssemblerLabel(CodeAssembler *assembler, CodeAssemblerLabel::Type type=CodeAssemblerLabel::kNonDeferred)
std::map< CodeAssemblerVariable::Impl *, Node *, CodeAssemblerVariable::ImplComparator > variable_phis_
CodeAssemblerLabel(CodeAssembler *assembler, const CodeAssemblerVariableList &merged_variables, CodeAssemblerLabel::Type type=CodeAssemblerLabel::kNonDeferred)
CodeAssemblerLabel(CodeAssembler *assembler, CodeAssemblerVariable *merged_variable, CodeAssemblerLabel::Type type=CodeAssemblerLabel::kNonDeferred)
CodeAssemblerLabel(const CodeAssemblerLabel &)=delete
CodeAssemblerParameterizedLabelBase(CodeAssembler *assembler, size_t arity, CodeAssemblerLabel::Type type)
const std::vector< Node * > & CreatePhis(std::vector< MachineRepresentation > representations)
Node * CreatePhi(MachineRepresentation rep, const std::vector< Node * > &inputs)
CodeAssemblerParameterizedLabel(CodeAssembler *assembler, CodeAssemblerLabel::Type type)
static void AssignPhi(TNode< T > *result, Node *phi)
std::vector< FileAndLine > macro_call_stack_
std::vector< CodeAssemblerExceptionHandlerLabel * > exception_handler_labels_
std::unique_ptr< RawMachineAssembler > raw_assembler_
CodeAssemblerState(const CodeAssemblerState &)=delete
CodeAssemblerState & operator=(const CodeAssemblerState &)=delete
ZoneSet< CodeAssemblerVariable::Impl *, CodeAssemblerVariable::ImplComparator > variables_
CodeAssemblerVariable & operator=(const CodeAssemblerVariable &)=delete
CodeAssemblerVariable(const CodeAssemblerVariable &)=delete
std::deque< std::unique_ptr< TurbofanCompilationJob > > main_thread_output_queue_
CheckedNode(compiler::Node *node, CodeAssembler *, const char *)
TNode< BoolT > Word32NotEqual(TNode< Word32T > left, TNode< Word32T > right)
Node * CallCFunctionWithoutFunctionDescriptor(Node *function, MachineType return_type, std::initializer_list< CFunctionArg > args)
TNode< T > CallStub(const CallInterfaceDescriptor &descriptor, TNode< Code > target, TNode< Object > context, TArgs... args)
Node * CallCFunctionWithoutFunctionDescriptor(Node *function, MachineType return_type, CArgs... cargs)
TNode< IntPtrT > IntPtrMul(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > IntPtrAdd(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > WordOr(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > WordSar(TNode< IntPtrT > value, int shift)
CodeAssembler(CodeAssemblerState *state)
TNode< Int32T > Signed(TNode< Word32T > x)
std::pair< MachineType, Node * > CFunctionArg
CodeAssembler & operator=(const CodeAssembler &)=delete
void Comment(MessageWithSourceLocation message, Args &&... args)
TNode< RawPtrT > RawPtrSub(TNode< RawPtrT > left, TNode< IntPtrT > right)
TNode< RawPtrT > SwitchToTheCentralStack()
TNode< UintPtrT > Unsigned(TNode< WordT > x)
TNode< Int64T > Signed(TNode< Word64T > x)
Node * CallCFunctionWithCallerSavedRegisters(Node *function, MachineType return_type, SaveFPRegsMode mode, CArgs... cargs)
CodeAssembler(const CodeAssembler &)=delete
TNode< T > UncheckedCast(Node *value)
TNode< IntPtrT > WordShl(TNode< IntPtrT > left, TNode< IntegralT > right)
Node * CallCFunction(Node *function, std::optional< MachineType > return_type, std::initializer_list< CFunctionArg > args)
TNode< Int64T > Int64Mul(TNode< Int64T > left, TNode< Int64T > right)
TNode< Type > HeapConstantHole(Handle< Type > object)
TNode< Int32T > Int32Mul(TNode< Int32T > left, TNode< Int32T > right)
TNode< BoolT > WordEqual(TNode< WordT > left, TNode< WordT > right)
TNode< Word32T > AtomicOr(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
TNode< Int32T > Word32Shl(TNode< Int32T > left, int right)
TNode< Uint64T > Word64Not(TNode< Uint64T > value)
TNode< UintPtrT > UintPtrSub(TNode< UintPtrT > left, TNode< UintPtrT > right)
TNode< IntPtrT > WordSar(TNode< IntPtrT > left, TNode< IntegralT > right)
void CallBuiltinVoid(Builtin id, TNode< Object > context, TArgs... args)
TNode< Int32T > Word32BitwiseNot(TNode< Int32T > a)
TNode< RawPtrT > SwitchToTheCentralStackIfNeeded()
TNode< Uint32T > Uint64HighWordConstantNoLowWord(uint64_t value)
TNode< Word32T > AtomicExchange(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
TNode< Type > HeapConstantMaybeHole(Handle< Type > object)
TNode< Uint32T > Unsigned(TNode< Word32T > x)
TNode< Int32T > Word32And(TNode< Int32T > left, TNode< Int32T > right)
Node * CallCFunctionWithCallerSavedRegisters(Node *function, MachineType return_type, SaveFPRegsMode mode, std::initializer_list< CFunctionArg > args)
TNode< Word32T > AtomicAdd(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
TNode< Int32T > Int32Sub(TNode< Int32T > left, int right)
void TailCallJSBuiltin(Builtin id, TNode< Object > context, TNode< Object > function, TNode< Object > new_target, TNode< Int32T > arg_count, TNode< JSDispatchHandleT > dispatch_handle)
TNode< Uint32T > UniqueUint32Constant(int32_t value)
TNode< Type > Load(MachineType type, TNode< RawPtr< Type > > base)
TNode< Uint64T > Unsigned(TNode< Word64T > x)
void Branch(TNode< BoolT > condition, CodeAssemblerParameterizedLabel< T... > *if_true, std::vector< Node * > args_true, CodeAssemblerParameterizedLabel< U... > *if_false, std::vector< Node * > args_false)
TNode< T > ReinterpretCast(Node *value)
void Goto(CodeAssemblerParameterizedLabel< T... > *label, Args... args)
TNode< Int32T > Int32Add(TNode< Int32T > left, TNode< Int32T > right)
CheckedNode< T, true > Cast(TNode< T > value, const char *location="")
TNode< Uint32T > Word32Shl(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< IntPtrT > BitcastTaggedToWord(TNode< Smi > node)
TNode< Uint32T > Word32And(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< Uint64T > Uint64Constant(uint64_t value)
void TailCallRuntime(Runtime::FunctionId function, TNode< Object > context, TArgs... args)
TNode< JSAny > ConstructJS(Builtin builtin, TNode< Context > context, TNode< Object > function, TNode< JSAny > new_target, TArgs... args)
TNode< BoolT > Word32And(TNode< BoolT > left, TNode< BoolT > right)
TNode< Uint32T > Word32Or(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< Uint64T > Uint64Add(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< Uint32T > Unsigned(TNode< Uint32T > x)
TNode< BoolT > Word32Or(TNode< BoolT > left, TNode< BoolT > right)
TNode< BoolT > Word64NotEqual(TNode< Word64T > left, TNode< Word64T > right)
TNode< Type > Load(Node *base, TNode< WordT > offset)
TNode< BoolT > Word32Equal(TNode< Word32T > left, int right)
TNode< IntPtrT > RawPtrSub(TNode< RawPtrT > left, TNode< RawPtrT > right)
TNode< Uint64T > Word64Shr(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< UintPtrT > WordAnd(TNode< UintPtrT > left, TNode< UintPtrT > right)
TNode< Int64T > Word64Sar(TNode< Int64T > left, TNode< Int64T > right)
void Bind(CodeAssemblerParameterizedLabel< T... > *label, TNode< T > *... phis)
TNode< T > UncheckedCast(TNode< U > value)
TNode< Type > AtomicOr64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
TNode< Int32T > Int32Sub(TNode< Int32T > left, TNode< Int32T > right)
TNode< Int32T > Word32Or(TNode< Int32T > left, TNode< Int32T > right)
TNode< Object > CallJSBuiltin(Builtin builtin, TNode< Context > context, TNode< Object > function, std::optional< TNode< Object > > new_target, TNode< Object > receiver, TArgs... args)
TNode< Int32T > Word32Shl(TNode< Int32T > left, TNode< Int32T > right)
TNode< BoolT > IntPtrEqual(TNode< WordT > left, TNode< WordT > right)
TNode< IntPtrT > WordAnd(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< Type > AtomicSub64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
TNode< Type > AtomicExchange64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
void TailCallBuiltinThenBytecodeDispatch(Builtin builtin, Node *context, TArgs... args)
TNode< Uint64T > Uint64Mul(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< Word32T > Word32And(TNode< Word32T > left, int right)
TNode< Int64T > Word64And(TNode< Int64T > left, TNode< Int64T > right)
TNode< ExternalPointerHandleT > ExternalPointerHandleNullConstant()
TNode< Int64T > Int64Sub(TNode< Int64T > left, TNode< Int64T > right)
TNode< IntPtrT > IntPtrSub(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > WordShr(TNode< IntPtrT > value, int shift)
void TailCallBuiltin(Builtin id, TNode< Object > context, TArgs... args)
TNode< Word32T > AtomicXor(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
TNode< typename std::tuple_element< index, std::tuple< T1, T2 > >::type > Projection(TNode< PairT< T1, T2 > > value)
void TailCallRuntime(Runtime::FunctionId function, TNode< Int32T > arity, TNode< Object > context, TArgs... args)
TNode< Uint32T > Uint64HighWordConstant(uint64_t value)
TNode< Uint32T > Uint32Sub(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< Int64T > Word64Xor(TNode< Int64T > left, TNode< Int64T > right)
TNode< Type > AtomicXor64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
TNode< Int64T > Int64Add(TNode< Int64T > left, TNode< Int64T > right)
TNode< BoolT > BoolConstant(bool value)
TNode< Uint64T > Word64And(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< Int64T > Word64Shr(TNode< Int64T > left, TNode< Uint64T > right)
TNode< Uint32T > Word32Shr(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< Word32T > AtomicSub(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
TNode< Uint64T > Uint64Sub(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< Uint32T > Uint64LowWordConstant(uint64_t value)
TNode< Uint64T > Word64Xor(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< BoolT > WordNotEqual(TNode< WordT > left, TNode< WordT > right)
TNode< Type > AtomicAdd64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
TNode< T > CallBuiltinPointer(const CallInterfaceDescriptor &descriptor, TNode< BuiltinPtr > target, TNode< Object > context, TArgs... args)
Node * CallCFunction(Node *function, std::optional< MachineType > return_type, CArgs... cargs)
TNode< Uint32T > Uint32Add(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< RawPtrT > PointerConstant(void *value)
TNode< Uint32T > Uint32Constant(uint32_t value)
TNode< Type > HeapConstantNoHole(Handle< Type > object)
TNode< Type > UnalignedLoad(TNode< RawPtrT > base, TNode< IntPtrT > offset)
TNode< Int32T > Word32Sar(TNode< Int32T > left, TNode< Int32T > right)
TNode< BoolT > Word32Equal(TNode< Word32T > left, TNode< Word32T > right)
TNode< T > CallRuntime(Runtime::FunctionId function, TNode< Object > context, TArgs... args)
TNode< Word32T > AtomicAnd(MachineType type, TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< Word32T > value)
void SwitchFromTheCentralStack(TNode< RawPtrT > old_sp)
TNode< Uint64T > Word64Shl(TNode< Uint64T > left, TNode< Uint64T > right)
TNode< Uint32T > Uint32Mul(TNode< Uint32T > left, TNode< Uint32T > right)
TNode< IntPtrT > WordNot(TNode< IntPtrT > a)
TNode< UintPtrT > UintPtrConstant(uintptr_t value)
void TailCallStub(const CallInterfaceDescriptor &descriptor, TNode< Code > target, TNode< Object > context, TArgs... args)
void Branch(TNode< BoolT > condition, CodeAssemblerParameterizedLabel< T... > *if_true, CodeAssemblerParameterizedLabel< T... > *if_false, Args... args)
TNode< UintPtrT > WordShl(TNode< UintPtrT > left, TNode< IntegralT > right)
TNode< JSAny > CallJS(Builtin builtin, TNode< Context > context, TNode< Object > function, TNode< JSAny > receiver, TArgs... args)
TNode< Type > AtomicLoad(AtomicMemoryOrder order, TNode< RawPtrT > base, TNode< WordT > offset)
TNode< RawPtrT > RawPtrAdd(TNode< RawPtrT > left, TNode< IntPtrT > right)
TNode< Int64T > Word64Shl(TNode< Int64T > left, TNode< Int64T > right)
TNode< UintPtrT > WordShr(TNode< UintPtrT > left, TNode< IntegralT > right)
TNode< Int32T > Signed(TNode< Int32T > x)
TNode< IntPtrT > Signed(TNode< WordT > x)
TNode< UintPtrT > UintPtrAdd(TNode< UintPtrT > left, TNode< UintPtrT > right)
TNode< Int64T > Word64Not(TNode< Int64T > value)
TNode< T > CallBuiltin(Builtin id, TNode< Object > context, TArgs... args)
TNode< T > Parameter(int value, const SourceLocation &loc=SourceLocation::Current())
Node * CallStubR(StubCallMode call_mode, const CallInterfaceDescriptor &descriptor, TNode< Object > target, TNode< Object > context, TArgs... args)
TNode< Type > AtomicAnd64(TNode< RawPtrT > base, TNode< UintPtrT > offset, TNode< UintPtrT > value, TNode< UintPtrT > value_high)
CheckedNode< Object, false > Cast(Node *value, const char *location="")
TNode< BoolT > Word64Equal(TNode< Word64T > left, TNode< Word64T > right)
TypedCodeAssemblerVariable< Object > * exception_
std::unique_ptr< CodeAssemblerExceptionHandlerLabel > label_
void operator=(const TypedCodeAssemblerVariable< T > &variable)
TypedCodeAssemblerVariable(TNode< T > initial_value, CodeAssembler *assembler)
#define DECLARE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType)
#define CODE_ASSEMBLER_UNARY_OP_LIST(V)
#define OBJECT_TYPE_STRUCT_CASE(NAME, Name, name)
#define DECLARE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type)
#define OBJECT_TYPE_ODDBALL_CASE(Name)
#define OBJECT_TYPE_CASE(Name)
#define CODE_ASSEMBLER_BINARY_OP_LIST(V)
#define OBJECT_TYPE_TEMPLATE_CASE(Name)
#define MAKE_FORWARD_DECLARATION(Name)
#define CAST(x)
MachineType mt
#define DEBUG_BOOL
Definition globals.h:87
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
Label label
Isolate * isolate
int32_t offset
TNode< Object > receiver
ZoneVector< RpoNumber > & result
Builtin builtin
LinkageLocation location_
int x
const char * name_
int s
Definition mul-fft.cc:297
constexpr bool has_type_v
NumberConstant(std::numeric_limits< double >::quiet_NaN())) DEFINE_GETTER(EmptyStateValues
std::function< void()> CodeAssemblerCallback
TNode< Float64T > Float64Add(TNode< Float64T > a, TNode< Float64T > b)
HeapConstantNoHole(BUILTIN_CODE(isolate(), AllocateInOldGeneration))) DEFINE_GETTER(ArrayConstructorStubConstant
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
Node::Uses::const_iterator begin(const Node::Uses &uses)
Definition node.h:708
constexpr int kJSCallClosureParameterIndex
Definition globals.h:2789
constexpr JSDispatchHandle kInvalidDispatchHandle(0xffffffff<< kJSDispatchHandleShift)
MaybeWeak< HeapObject > HeapObjectReference
Definition globals.h:1204
Handle< To > UncheckedCast(Handle< From > value)
Definition handles-inl.h:55
constexpr int U
bool NeedsBoundsCheck(CheckBounds check_bounds)
bool IsSubtype(MachineRepresentation rep1, MachineRepresentation rep2)
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int JSParameterCount(int param_count_without_receiver)
Definition globals.h:2782
constexpr bool Is64()
constexpr MachineRepresentation PhiMachineRepresentationOf
Definition tnode.h:286
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
V8_INLINE Local< Primitive > Null(Isolate *isolate)
V8_INLINE Local< Boolean > True(Isolate *isolate)
V8_INLINE Local< Boolean > False(Isolate *isolate)
V8_INLINE Local< Primitive > Undefined(Isolate *isolate)
i::Address Load(i::Address address)
Definition unwinder.cc:19
void Dummy(char *arg)
Definition d8.cc:4558
#define HEAP_OBJECT_TRUSTED_TYPE_LIST(V)
#define HEAP_OBJECT_TEMPLATE_TYPE_LIST(V)
#define VIRTUAL_OBJECT_TYPE_LIST(V)
#define OBJECT_TYPE_LIST(V)
#define HEAP_OBJECT_ORDINARY_TYPE_LIST(V)
#define STRUCT_LIST(V)
std::ostream & operator<<(std::ostream &os, const Operation &operation)
Definition operation.h:49
Node * node_
#define DCHECK_WITH_MSG(condition, msg)
Definition logging.h:182
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
V8_INLINE A implicit_cast(A x)
Definition macros.h:306
#define V8_EXPORT_PRIVATE
Definition macros.h:460
MessageWithSourceLocation(const char *message, const SourceLocation &loc=SourceLocation::Current())
#define V8_NODISCARD
Definition v8config.h:693
std::unique_ptr< ValueMirror > value