v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
opmasks.h
Go to the documentation of this file.
1// Copyright 2023 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_TURBOSHAFT_OPMASKS_H_
6#define V8_COMPILER_TURBOSHAFT_OPMASKS_H_
7
10
11// The Opmasks allow performing a type check or cast with an operation mask
12// that doesn't only encode the opcode but also additional properties, i.e.
13// fields of an operation.
14// The type check will be expressed by masking out the first 8 bytes of the
15// object based on a generic Opmask and then comparing it against a specific
16// shape of that mask.
17//
18// Given the following operation and mask definitions:
19//
20// struct ConvertOp : FixedArityOperationT<1, ConvertOp> {
21// enum Type : int8_t {kBool, kInt, kFloat};
22// Type from;
23// Type to;
24// };
25//
26// using ConvertOpMask =
27// MaskBuilder<ConvertOp, FIELD(ConvertOp, from), FIELD(ConvertOp, to)>;
28// using ConvertOpTargetMask = MaskBuilder<ConvertOp, FIELD(ConvertOp, to)>;
29//
30// using ConvertFloatToInt =
31// ConvertOpMask::For<ConvertOp::kFloat, ConvertOp::kInt>;
32// using ConvertToInt =
33// ConvertOpTargetMask::For<ConvertOp::kInt>;
34//
35// The masks can be used in the following way:
36//
37// const Operation& my_op = ...;
38// bool is_float_to_int = my_op.Is<ConvertFloatToInt>();
39// const ConvertOp* to_int = my_op.TryCast<ConvertToInt>();
40//
41// Where to_int will be non-null iff my_op is a ConvertOp *and* the target type
42// is int.
43
45
47
48template <typename T, size_t Offset>
50 using type = T;
51 static constexpr size_t offset = Offset;
52 static constexpr size_t size = sizeof(T);
53
54 static_assert(offset + size <= sizeof(uint64_t));
55};
56
57template <typename T>
58constexpr uint64_t encode_for_mask(T value) {
59 return static_cast<uint64_t>(value);
60}
61
62template <typename T>
64 using type = T;
65};
66template <>
70template <>
74template <>
78
79template <typename Op, typename... Fields>
81 static constexpr uint64_t BuildBaseMask() {
82 static_assert(OFFSET_OF(Operation, opcode) == 0);
83 static_assert(sizeof(Operation::opcode) == sizeof(uint8_t));
84 static_assert(sizeof(Operation) == 4);
85#if V8_TARGET_BIG_ENDIAN
86 return static_cast<uint64_t>(0xFF)
87 << ((sizeof(uint64_t) - sizeof(uint8_t)) * kBitsPerByte);
88#else
89 return static_cast<uint64_t>(0xFF);
90#endif
91 }
92
93 static constexpr uint64_t EncodeBaseValue(Opcode opcode) {
94 static_assert(OFFSET_OF(Operation, opcode) == 0);
95#if V8_TARGET_BIG_ENDIAN
96 return static_cast<uint64_t>(opcode)
97 << ((sizeof(uint64_t) - sizeof(Operation::opcode)) * kBitsPerByte);
98#else
99 return static_cast<uint64_t>(opcode);
100#endif
101 }
102
103 static constexpr uint64_t BuildMask() {
104 constexpr uint64_t base_mask = BuildBaseMask();
105 return (base_mask | ... | BuildFieldMask<Fields>());
106 }
107
108 static constexpr uint64_t EncodeValue(typename Fields::type... args) {
109 constexpr uint64_t base_mask = EncodeBaseValue(operation_to_opcode_v<Op>);
110 return (base_mask | ... | EncodeFieldValue<Fields>(args));
111 }
112
113 template <typename F>
114 static constexpr uint64_t BuildFieldMask() {
115 static_assert(F::size < sizeof(uint64_t));
116 static_assert(F::offset + F::size <= sizeof(uint64_t));
117 constexpr uint64_t ones = static_cast<uint64_t>(-1) >>
118 ((sizeof(uint64_t) - F::size) * kBitsPerByte);
119#if V8_TARGET_BIG_ENDIAN
120 return ones << ((sizeof(uint64_t) - F::size - F::offset) * kBitsPerByte);
121#else
122 return ones << (F::offset * kBitsPerByte);
123#endif
124 }
125
126 template <typename F>
127 static constexpr uint64_t EncodeFieldValue(typename F::type value) {
128#if V8_TARGET_BIG_ENDIAN
129 return encode_for_mask(value)
130 << ((sizeof(uint64_t) - F::size - F::offset) * kBitsPerByte);
131#else
132 return encode_for_mask(value) << (F::offset * kBitsPerByte);
133#endif
134 }
135
136 template <typename Fields::type... Args>
137 using For = OpMaskT<Op, BuildMask(), EncodeValue(Args...)>;
138};
139
140// === Definitions of masks for Turboshaft operations === //
141
145
158
177
180
187
189 FIELD(FloatUnaryOp, rep)>;
190
197
199 FIELD(FloatBinopOp, rep)>;
200
209
213
215 ShiftMask::For<ShiftOp::Kind::kShiftLeft, WordRepresentation::Word32()>;
217 ShiftMask::For<ShiftOp::Kind::kShiftRightArithmetic,
220 ShiftMask::For<ShiftOp::Kind::kShiftRightArithmeticShiftOutZeros,
223 ShiftMask::For<ShiftOp::Kind::kShiftRightLogical,
226 ShiftMask::For<ShiftOp::Kind::kRotateRight, WordRepresentation::Word32()>;
228 ShiftMask::For<ShiftOp::Kind::kShiftLeft, WordRepresentation::Word64()>;
230 ShiftMask::For<ShiftOp::Kind::kShiftRightArithmetic,
233 ShiftMask::For<ShiftOp::Kind::kShiftRightLogical,
236
239
241
247
249
252
254 FIELD(ComparisonOp, rep)>;
255
262
265 FIELD(ChangeOp, from), FIELD(ChangeOp, to)>;
266
291
295
302
314
321
322#if V8_ENABLE_WEBASSEMBLY
323
324using Simd128BinopMask =
325 MaskBuilder<Simd128BinopOp, FIELD(Simd128BinopOp, kind)>;
326using kSimd128I32x4Mul = Simd128BinopMask::For<Simd128BinopOp::Kind::kI32x4Mul>;
327using kSimd128I16x8Mul = Simd128BinopMask::For<Simd128BinopOp::Kind::kI16x8Mul>;
328using kSimd128AndNot = Simd128BinopMask::For<Simd128BinopOp::Kind::kS128AndNot>;
329using kSimd128Xor = Simd128BinopMask::For<Simd128BinopOp::Kind::kS128Xor>;
330
331#define SIMD_SIGN_EXTENSION_BINOP_MASK(kind) \
332 using kSimd128##kind = Simd128BinopMask::For<Simd128BinopOp::Kind::k##kind>;
333FOREACH_SIMD_128_BINARY_SIGN_EXTENSION_OPCODE(SIMD_SIGN_EXTENSION_BINOP_MASK)
334#undef SIMD_SIGN_EXTENSION_BINOP_MASK
335
336using Simd128UnaryMask =
337 MaskBuilder<Simd128UnaryOp, FIELD(Simd128UnaryOp, kind)>;
338#define SIMD_UNARY_MASK(kind) \
339 using kSimd128##kind = Simd128UnaryMask::For<Simd128UnaryOp::Kind::k##kind>;
340FOREACH_SIMD_128_UNARY_OPCODE(SIMD_UNARY_MASK)
341#undef SIMD_UNARY_MASK
342
343using Simd128ShiftMask =
344 MaskBuilder<Simd128ShiftOp, FIELD(Simd128ShiftOp, kind)>;
345#define SIMD_SHIFT_MASK(kind) \
346 using kSimd128##kind = Simd128ShiftMask::For<Simd128ShiftOp::Kind::k##kind>;
347FOREACH_SIMD_128_SHIFT_OPCODE(SIMD_SHIFT_MASK)
348#undef SIMD_SHIFT_MASK
349
350using Simd128LoadTransformMask =
351 MaskBuilder<Simd128LoadTransformOp,
352 FIELD(Simd128LoadTransformOp, transform_kind)>;
353#define SIMD_LOAD_TRANSFORM_MASK(kind) \
354 using kSimd128LoadTransform##kind = Simd128LoadTransformMask::For< \
355 Simd128LoadTransformOp::TransformKind::k##kind>;
356FOREACH_SIMD_128_LOAD_TRANSFORM_OPCODE(SIMD_LOAD_TRANSFORM_MASK)
357#undef SIMD_LOAD_TRANSFORM_MASK
358
359using Simd128ReplaceLaneMask =
360 MaskBuilder<Simd128ReplaceLaneOp, FIELD(Simd128ReplaceLaneOp, kind)>;
361using kSimd128ReplaceLaneF32x4 =
362 Simd128ReplaceLaneMask::For<Simd128ReplaceLaneOp::Kind::kF32x4>;
363
364#if V8_ENABLE_WASM_SIMD256_REVEC
365using Simd256UnaryMask =
366 MaskBuilder<Simd256UnaryOp, FIELD(Simd256UnaryOp, kind)>;
367#define SIMD256_UNARY_MASK(kind) \
368 using kSimd256##kind = Simd256UnaryMask::For<Simd256UnaryOp::Kind::k##kind>;
369FOREACH_SIMD_256_UNARY_OPCODE(SIMD256_UNARY_MASK)
370#undef SIMD256_UNARY_MASK
371
372#endif // V8_ENABLE_WASM_SIMD256_REVEC
373
374#endif // V8_ENABLE_WEBASSEMBLY
375
376#undef FIELD
377
378} // namespace v8::internal::compiler::turboshaft::Opmask
379
380#endif // V8_COMPILER_TURBOSHAFT_OPMASKS_H_
#define T
Builtins::Kind kind
Definition builtins.cc:40
static constexpr FloatRepresentation Float32()
static constexpr FloatRepresentation Float64()
static constexpr RegisterRepresentation Word32()
static constexpr RegisterRepresentation Float64()
static constexpr RegisterRepresentation WordPtr()
static constexpr RegisterRepresentation Float32()
static constexpr RegisterRepresentation Word64()
static constexpr RegisterRepresentation Tagged()
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
constexpr uint64_t encode_for_mask(T value)
Definition opmasks.h:58
constexpr Opcode operation_to_opcode_v
Definition operations.h:397
constexpr int kBitsPerByte
Definition globals.h:682
FIELD(name, comment, camel)
constexpr AddrMode Offset
return value
Definition map-inl.h:893
Operation
Definition operation.h:43
#define OFFSET_OF(type, field)
Definition macros.h:57
static constexpr uint64_t EncodeValue(typename Fields::type... args)
Definition opmasks.h:108
static constexpr uint64_t EncodeBaseValue(Opcode opcode)
Definition opmasks.h:93
static constexpr uint64_t EncodeFieldValue(typename F::type value)
Definition opmasks.h:127