v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
index.h
Go to the documentation of this file.
1// Copyright 2022 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_INDEX_H_
6#define V8_COMPILER_TURBOSHAFT_INDEX_H_
7
8#include <stdint.h>
9
10#include <cstddef>
11#include <optional>
12#include <type_traits>
13
14#include "src/base/logging.h"
15#include "src/codegen/tnode.h"
20#include "src/objects/oddball.h"
21#include "src/objects/string.h"
22#include "src/objects/tagged.h"
23
24#define TURBOSHAFT_ALLOW_IMPLICIT_OPINDEX_INITIALIZATION_FOR_V 1
25
27
28// Operations are stored in possibly multiple sequential storage slots.
29using OperationStorageSlot = uint64_t;
30// Operations occupy at least 2 slots, therefore we assign one id per two slots.
31constexpr size_t kSlotsPerId = 2;
32
33template <typename T, typename C>
34class ConstOrV;
35
36// `OpIndex` is an offset from the beginning of the operations buffer.
37// Compared to `Operation*`, it is more memory efficient (32bit) and stable when
38// the operations buffer is re-allocated.
39class OpIndex {
40 protected:
41 // We make this constructor protected so that integers are not easily
42 // convertible to OpIndex. FromOffset should be used instead to create an
43 // OpIndex from an offset.
44 explicit constexpr OpIndex(uint32_t offset) : offset_(offset) {
45 SLOW_DCHECK(CheckInvariants());
46 }
47 friend class OperationBuffer;
48
49 public:
50 static constexpr OpIndex FromOffset(uint32_t offset) {
51 return OpIndex(offset);
52 }
53 constexpr OpIndex() : offset_(std::numeric_limits<uint32_t>::max()) {}
54 template <typename T, typename C>
55 OpIndex(const ConstOrV<T, C>&) { // NOLINT(runtime/explicit)
57 "Cannot initialize OpIndex from ConstOrV<>. Did you forget "
58 "to resolve() it in the assembler?");
59 }
60
61 constexpr uint32_t id() const {
62 // Operations are stored at an offset that's a multiple of
63 // `sizeof(OperationStorageSlot)`. In addition, an operation occupies at
64 // least `kSlotsPerId` many `OperationSlot`s. Therefore, we can assign id's
65 // by dividing by `kSlotsPerId`. A compact id space is important, because it
66 // makes side-tables smaller.
67 SLOW_DCHECK(CheckInvariants());
68 return offset_ / sizeof(OperationStorageSlot) / kSlotsPerId;
69 }
70 uint32_t hash() const {
71 // It can be useful to hash OpIndex::Invalid(), so we have this `hash`
72 // function, which returns the id, but without DCHECKing that Invalid is
73 // valid.
74 SLOW_DCHECK_IMPLIES(valid(), CheckInvariants());
75 return offset_ / sizeof(OperationStorageSlot) / kSlotsPerId;
76 }
77 uint32_t offset() const {
78 SLOW_DCHECK(CheckInvariants());
79#ifdef DEBUG
81#else
82 return offset_;
83#endif
84 }
85
86 constexpr bool valid() const { return *this != Invalid(); }
87
88 static constexpr OpIndex Invalid() { return OpIndex(); }
89
90 // Encode a sea-of-nodes node id in the `OpIndex` type.
91 // Only used for node origins that actually point to sea-of-nodes graph nodes.
92 static OpIndex EncodeTurbofanNodeId(uint32_t id) {
94 result.offset_ += kTurbofanNodeIdFlag;
95 return result;
96 }
97 uint32_t DecodeTurbofanNodeId() const {
99 return offset_ / sizeof(OperationStorageSlot);
100 }
101 bool IsTurbofanNodeId() const {
103 }
104
105 constexpr bool operator==(OpIndex other) const {
106 return offset_ == other.offset_;
107 }
108 constexpr bool operator!=(OpIndex other) const {
109 return offset_ != other.offset_;
110 }
111 constexpr bool operator<(OpIndex other) const {
112 return offset_ < other.offset_;
113 }
114 constexpr bool operator>(OpIndex other) const {
115 return offset_ > other.offset_;
116 }
117 constexpr bool operator<=(OpIndex other) const {
118 return offset_ <= other.offset_;
119 }
120 constexpr bool operator>=(OpIndex other) const {
121 return offset_ >= other.offset_;
122 }
123
124#ifdef DEBUG
125 int generation_mod2() const {
127 }
128 void set_generation_mod2(int generation_mod2) {
129 DCHECK_LE(generation_mod2, 1);
130 offset_ |= generation_mod2 << kGenerationMaskShift;
131 }
132
133 constexpr bool CheckInvariants() const {
134 DCHECK(valid());
135 // The second lowest significant bit of the offset is used to store the
136 // graph generation modulo 2. The lowest and 3rd lowest bits should always
137 // be 0 (as long as sizeof(OperationStorageSlot) is 8).
138 static_assert(sizeof(OperationStorageSlot) == 8);
139 return (offset_ & 0b101) == 0;
140 }
141#endif
142
143 protected:
144 static constexpr uint32_t kGenerationMaskShift = 1;
145 static constexpr uint32_t kGenerationMask = 1 << kGenerationMaskShift;
146 static constexpr uint32_t kUnmaskGenerationMask = ~kGenerationMask;
147
148 // In DEBUG builds, the offset's second lowest bit contains the graph
149 // generation % 2, so one should keep this in mind when looking at the value
150 // of the offset.
151 uint32_t offset_;
152
153 static constexpr uint32_t kTurbofanNodeIdFlag = 1;
154
155 template <typename H>
156 friend H AbslHashValue(H h, const OpIndex& idx) {
157 return H::combine(std::move(h), idx.offset_);
158 }
159};
160
161V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, OpIndex idx);
162
163class OptionalOpIndex : protected OpIndex {
164 public:
165 using OpIndex::OpIndex;
166 using OpIndex::valid;
167
168 constexpr OptionalOpIndex(OpIndex other) // NOLINT(runtime/explicit)
169 : OpIndex(other) {}
170
171 static constexpr OptionalOpIndex Nullopt() {
173 }
174
175 uint32_t hash() const { return OpIndex::hash(); }
176
177 constexpr bool has_value() const { return valid(); }
178 constexpr OpIndex value() const {
179 DCHECK(has_value());
180 return OpIndex(*this);
181 }
182 constexpr OpIndex value_or_invalid() const { return OpIndex(*this); }
183
184 template <typename H>
185 friend H AbslHashValue(H h, const OptionalOpIndex& idx) {
186 return H::combine(std::move(h), idx.offset_);
187 }
188};
189
190V8_INLINE std::ostream& operator<<(std::ostream& os, OptionalOpIndex idx) {
191 return os << idx.value_or_invalid();
192}
193
194// Dummy value for abstract representation classes that don't have a
195// RegisterRepresentation.
196struct nullrep_t {};
198constexpr inline bool operator==(nullrep_t, nullrep_t) { return true; }
200 return false;
201}
203 return false;
204}
205constexpr inline bool operator!=(nullrep_t, nullrep_t) { return false; }
207 return true;
208}
210 return true;
211}
212
213// Abstract tag classes for V<>.
214struct Any {};
215struct None {};
216
217template <size_t Bits>
218struct WordWithBits : public Any {
219 static constexpr int bits = Bits;
220 static_assert(Bits == 32 || Bits == 64 || Bits == 128 || Bits == 256);
221};
222
225using WordPtr = std::conditional_t<Is64(), Word64, Word32>;
226
227template <size_t Bits>
228struct FloatWithBits : public Any { // FloatAny {
229 static constexpr int bits = Bits;
230 static_assert(Bits == 32 || Bits == 64);
231};
232
235
238
239struct Compressed : public Any {};
240struct InternalTag : public Any {};
241struct FrameState : public InternalTag {};
242
243// A Union type for untagged values. For Tagged types use `Union` for now.
244// TODO(nicohartmann@): We should think about a more uniform solution some day.
245template <typename... Ts>
246struct UntaggedUnion : public Any {
248};
249
250template <typename... Ts>
251struct Tuple : public Any {
253 template <int Index>
255};
256
257// Traits classes `v_traits<T>` to provide additional T-specific information for
258// V<T> and ConstOrV<T>. If you need to provide non-default conversion behavior
259// for a specific type, specialize the corresponding v_traits<>.
260template <typename T, typename = void>
261struct v_traits;
262
263template <>
264struct v_traits<Any> {
265 static constexpr bool is_abstract_tag = true;
267 static constexpr auto rep = nullrep;
269 return true;
270 }
271
272 template <typename U>
273 struct implicitly_constructible_from : std::true_type {};
274};
275
276template <>
277struct v_traits<None> {
278 static constexpr bool is_abstract_tag = true;
280 static constexpr auto rep = nullrep;
282 return false;
283 }
284
285 template <typename U>
287 : std::bool_constant<std::is_same_v<U, None>> {};
288};
289
290template <>
292 static constexpr bool is_abstract_tag = true;
294 static constexpr auto rep = RegisterRepresentation::Compressed();
295 static constexpr bool allows_representation(
296 RegisterRepresentation maybe_allowed_rep) {
297 return maybe_allowed_rep == RegisterRepresentation::Compressed();
298 }
299
300 template <typename U>
302 : std::bool_constant<std::is_base_of_v<Compressed, U>> {};
303};
304
305template <>
307 static constexpr bool is_abstract_tag = true;
309 static constexpr auto rep = WordRepresentation::Word32();
310 using constexpr_type = uint32_t;
311 static constexpr bool allows_representation(
312 RegisterRepresentation maybe_allowed_rep) {
313 return maybe_allowed_rep == RegisterRepresentation::Word32();
314 }
315
316 template <typename U>
318 : std::bool_constant<std::is_base_of_v<Word32, U>> {};
319};
320
321template <>
323 static constexpr bool is_abstract_tag = true;
325 static constexpr auto rep = WordRepresentation::Word64();
326 using constexpr_type = uint64_t;
327 static constexpr bool allows_representation(
328 RegisterRepresentation maybe_allowed_rep) {
329 return maybe_allowed_rep == RegisterRepresentation::Word64();
330 }
331
332 template <typename U>
334 : std::bool_constant<std::is_base_of_v<Word64, U>> {};
335};
336
337template <>
339 static constexpr bool is_abstract_tag = true;
341 static constexpr auto rep = FloatRepresentation::Float32();
342 using constexpr_type = float;
343 static constexpr bool allows_representation(
344 RegisterRepresentation maybe_allowed_rep) {
345 return maybe_allowed_rep == RegisterRepresentation::Float32();
346 }
347
348 template <typename U>
350 : std::bool_constant<std::is_base_of_v<Float32, U>> {};
351};
352
353template <>
355 static constexpr bool is_abstract_tag = true;
357 static constexpr auto rep = FloatRepresentation::Float64();
358 using constexpr_type = double;
359 static constexpr bool allows_representation(
360 RegisterRepresentation maybe_allowed_rep) {
361 return maybe_allowed_rep == RegisterRepresentation::Float64();
362 }
363
364 template <typename U>
366 : std::bool_constant<std::is_base_of_v<Float64, U>> {};
367};
368
369template <>
371 static constexpr bool is_abstract_tag = true;
373 static constexpr auto rep = RegisterRepresentation::Simd128();
374 using constexpr_type = uint8_t[kSimd128Size];
375 static constexpr bool allows_representation(
376 RegisterRepresentation maybe_allowed_rep) {
377 return maybe_allowed_rep == RegisterRepresentation::Simd128();
378 }
379
380 template <typename U>
382 : std::bool_constant<std::is_base_of_v<Simd128, U>> {};
383};
384
385template <>
387 static constexpr bool is_abstract_tag = true;
389 static constexpr auto rep = RegisterRepresentation::Simd256();
390 using constexpr_type = uint8_t[kSimd256Size];
391 static constexpr bool allows_representation(
392 RegisterRepresentation maybe_allowed_rep) {
393 return maybe_allowed_rep == RegisterRepresentation::Simd256();
394 }
395
396 template <typename U>
398 : std::bool_constant<std::is_base_of_v<Simd256, U>> {};
399};
400
401template <typename T>
402struct v_traits<T, std::enable_if_t<is_taggable_v<T> && !is_union_v<T>>> {
403 static constexpr bool is_abstract_tag = false;
405 static constexpr auto rep = RegisterRepresentation::Tagged();
406 static constexpr bool allows_representation(
407 RegisterRepresentation maybe_allowed_rep) {
408 return maybe_allowed_rep == RegisterRepresentation::Tagged();
409 }
410
411 template <typename U>
413 : std::bool_constant<is_subtype<U, T>::value> {};
414 template <typename... Us>
416 : std::bool_constant<(
417 v_traits<T>::template implicitly_constructible_from<Us>::value &&
418 ...)> {};
419};
420
421template <typename T, typename... Ts>
422struct v_traits<Union<T, Ts...>> {
423 static_assert(!v_traits<T>::is_abstract_tag);
424 static_assert((!v_traits<Ts>::is_abstract_tag && ...));
425 static constexpr bool is_abstract_tag = false;
426 static_assert(((v_traits<T>::rep == v_traits<Ts>::rep) && ...));
427 static_assert((std::is_same_v<typename v_traits<T>::rep_type,
428 typename v_traits<Ts>::rep_type> &&
429 ...));
431 static constexpr auto rep = v_traits<T>::rep;
432 static constexpr bool allows_representation(
433 RegisterRepresentation maybe_allowed_rep) {
434 return maybe_allowed_rep == rep;
435 }
436
437 template <typename U>
439 : std::bool_constant<(
440 v_traits<T>::template implicitly_constructible_from<U>::value ||
441 ... ||
442 v_traits<Ts>::template implicitly_constructible_from<U>::value)> {};
443 template <typename... Us>
445 : std::bool_constant<(implicitly_constructible_from<Us>::value && ...)> {
446 };
447};
448
449namespace detail {
450template <typename T, bool SameStaticRep>
452 static constexpr auto rep = nullrep;
453};
454template <typename T>
456 static constexpr auto rep = v_traits<T>::rep;
457};
458template <typename T>
460template <typename T, typename... Ts>
462 : RepresentationForUnionBase<T, ((v_traits<T>::rep == v_traits<Ts>::rep) &&
463 ...)> {
464 private:
465 template <typename U>
466 struct to_rep_type {
467 using type = typename v_traits<U>::rep_type;
468 };
470
471 public:
472 using rep_type =
473 std::conditional_t<base::tmp::contains_v<rep_types, nullrep_t>, nullrep_t,
474 std::conditional_t<base::tmp::all_equal_v<rep_types>,
475 typename v_traits<T>::rep_type,
477};
478
479} // namespace detail
480
481template <typename... Ts>
482struct v_traits<UntaggedUnion<Ts...>> {
483 using rep_type =
484 typename detail::RepresentationForUnion<UntaggedUnion<Ts...>>::rep_type;
485 static constexpr auto rep =
487 static constexpr bool allows_representation(
488 RegisterRepresentation maybe_allowed_rep) {
489 return (v_traits<Ts>::allows_representation(maybe_allowed_rep) || ...);
490 }
491
492 template <typename U>
494 : std::bool_constant<(
495 v_traits<Ts>::template implicitly_constructible_from<U>::value ||
496 ...)> {};
497 template <typename... Us>
499 : std::bool_constant<(implicitly_constructible_from<Us>::value && ...)> {
500 };
501};
502
503template <typename T>
504struct v_traits<T, std::enable_if_t<std::is_base_of_v<InternalTag, T>>> {
506 static constexpr auto rep = nullrep;
507
508 template <typename U>
510 : std::bool_constant<std::is_same_v<T, U>> {};
511};
512
513template <typename... Ts>
514struct v_traits<Tuple<Ts...>> {
516 static constexpr auto rep = nullrep;
518 return false;
519 }
520
521 template <typename U>
522 struct implicitly_constructible_from : std::false_type {};
523
524 // NOTE: If you end up here with a compiler error
525 // "pack expansion contains parameter packs 'Ts' and 'Us' that have different
526 // lengths" this is most likely because you tried to convert between Tuple<>
527 // types of different sizes.
528 template <typename... Us>
530 : std::bool_constant<(
531 v_traits<Ts>::template implicitly_constructible_from<Us>::value &&
532 ...)> {};
533};
534
550
551template <typename T>
552concept IsUntagged =
553 !std::is_same_v<T, Any> &&
554 v_traits<Untagged>::implicitly_constructible_from<T>::value;
555
556template <typename T>
557concept IsTagged = !std::is_same_v<T, Any> &&
558 v_traits<Object>::implicitly_constructible_from<T>::value;
559
560#if V8_ENABLE_WEBASSEMBLY
561using WasmArrayNullable = Union<WasmArray, WasmNull>;
562using WasmStructNullable = Union<WasmStruct, WasmNull>;
563// The type for a nullable ref.string (stringref proposal). For imported strings
564// use StringOrNull instead.
565using WasmStringRefNullable = Union<String, WasmNull>;
566#endif
567
568template <typename T>
569constexpr bool IsWord() {
570 return std::is_same_v<T, Word32> || std::is_same_v<T, Word64> ||
571 std::is_same_v<T, Word>;
572}
573
574template <typename T>
576 if (std::is_same_v<T, Any>) return true;
577
578 switch (repr.value()) {
580 return std::is_same_v<T, Word> || std::is_same_v<T, Word32> ||
581 std::is_same_v<T, Untagged>;
583 return std::is_same_v<T, Word> || std::is_same_v<T, Word64> ||
584 std::is_same_v<T, Untagged>;
586 return std::is_same_v<T, Float> || std::is_same_v<T, Float32> ||
587 std::is_same_v<T, Untagged>;
589 return std::is_same_v<T, Float> || std::is_same_v<T, Float64> ||
590 std::is_same_v<T, Untagged>;
596 return std::is_same_v<T, Simd128>;
598 return std::is_same_v<T, Simd256>;
599 }
600}
601
602// V<> represents an SSA-value that is parameterized with the type of the value.
603// Types from the `Object` hierarchy can be provided as well as the abstract
604// representation classes (`Word32`, ...) defined above.
605// Prefer using V<> instead of a plain OpIndex where possible.
606template <typename T>
607class V : public OpIndex {
608 // V<T> is implicitly constructible from V<U> iff
609 // `v_traits<T>::implicitly_constructible_from<U>::value`. This is typically
610 // the case if T == U or T is a subclass of U. Different types may specify
611 // different conversion rules in the corresponding `v_traits` when necessary.
612 template <typename U>
613 constexpr static bool implicitly_constructible_from =
614 v_traits<T>::template implicitly_constructible_from<U>::value;
615
616 public:
617 using type = T;
618 static constexpr auto rep = v_traits<type>::rep;
619 constexpr V() : OpIndex() {}
620
621 // V<T> is implicitly constructible from V<U> iff
622 // `v_traits<T>::implicitly_constructible_from<U>::value`. This is typically
623 // the case if T == U or T is a subclass of U. Different types may specify
624 // different conversion rules in the corresponding `v_traits` when necessary.
625 template <typename U>
627 V(V<U> index) : OpIndex(index) {} // NOLINT(runtime/explicit)
628
629 static V Invalid() { return V<T>(OpIndex::Invalid()); }
630
631 template <typename U>
632 static V<T> Cast(V<U> index) {
633 return V<T>(OpIndex{index});
634 }
635 static V<T> Cast(OpIndex index) { return V<T>(index); }
636
637 static constexpr bool allows_representation(
638 RegisterRepresentation maybe_allowed_rep) {
639 return v_traits<T>::allows_representation(maybe_allowed_rep);
640 }
641
642#if !defined(TURBOSHAFT_ALLOW_IMPLICIT_OPINDEX_INITIALIZATION_FOR_V)
643
644 protected:
645#endif
646 // V<T> is implicitly constructible from plain OpIndex.
647 template <typename U>
648 requires(std::is_same_v<U, OpIndex>)
649 V(U index) : OpIndex(index) {} // NOLINT(runtime/explicit)
650};
651
652template <typename T>
654 // OptionalV<T> is implicitly constructible from OptionalV<U> iff
655 // `v_traits<T>::implicitly_constructible_from<U>::value`. This is typically
656 // the case if T == U or T is a subclass of U. Different types may specify
657 // different conversion rules in the corresponding `v_traits` when necessary.
658 template <typename U>
659 constexpr static bool implicitly_constructible_from =
660 v_traits<T>::template implicitly_constructible_from<U>::value;
661
662 public:
663 using type = T;
664 static constexpr auto rep = v_traits<type>::rep;
665 constexpr OptionalV() : OptionalOpIndex() {}
666
667 template <typename U>
669 OptionalV(OptionalV<U> index) // NOLINT(runtime/explicit)
670 : OptionalOpIndex(index) {}
671 template <typename U>
673 OptionalV(V<U> index) : OptionalOpIndex(index) {} // NOLINT(runtime/explicit)
674
676
677 constexpr V<T> value() const {
678 DCHECK(has_value());
680 }
681 constexpr V<T> value_or_invalid() const {
683 }
684
685 template <typename U>
687 return OptionalV<T>(OptionalOpIndex{index});
688 }
690 return OptionalV<T>(index);
691 }
692
693#if !defined(TURBOSHAFT_ALLOW_IMPLICIT_OPINDEX_INITIALIZATION_FOR_V)
694
695 protected:
696#endif
697 // OptionalV<T> is implicitly constructible from plain OptionalOpIndex.
698 template <typename U>
699 requires(std::is_same_v<U, OptionalOpIndex> || std::is_same_v<U, OpIndex>)
700 OptionalV(U index) : OptionalOpIndex(index) {} // NOLINT(runtime/explicit)
701};
702
703// Deduction guide for `OptionalV`.
704template <typename T>
706
707// ConstOrV<> is a generalization of V<> that allows constexpr values
708// (constants) to be passed implicitly. This allows reducers to write things
709// like
710//
711// __ Word32Add(value, 1)
712//
713// instead of having to write
714//
715// __ Word32Add(value, __ Word32Constant(1))
716//
717// which makes overall code more compact and easier to read. Functions need to
718// call `resolve` on the assembler in order to convert to V<> (which will then
719// construct the corresponding ConstantOp if the given ConstOrV<> holds a
720// constexpr value).
721// NOTICE: `ConstOrV<T>` can only be used if `v_traits<T>` provides a
722// `constexpr_type`.
723template <typename T, typename C = typename v_traits<T>::constexpr_type>
724class ConstOrV {
725 public:
726 using type = T;
727 using constant_type = C;
728
729 ConstOrV(constant_type value) // NOLINT(runtime/explicit)
730 : constant_value_(value), value_() {}
731
732 // ConstOrV<T> is implicitly constructible from V<U> iff V<T> is
733 // constructible from V<U>.
734 template <typename U>
735 ConstOrV(V<U> index) // NOLINT(runtime/explicit)
736 requires(std::is_constructible_v<V<T>, V<U>>)
737 : constant_value_(std::nullopt), value_(index) {}
738
739 bool is_constant() const { return constant_value_.has_value(); }
742 return *constant_value_;
743 }
744 V<type> value() const {
746 return value_;
747 }
748
749#if !defined(TURBOSHAFT_ALLOW_IMPLICIT_OPINDEX_INITIALIZATION_FOR_V)
750
751 protected:
752#endif
753 // ConstOrV<T> is implicitly constructible from plain OpIndex.
754 template <typename U>
755 ConstOrV(U index) // NOLINT(runtime/explicit)
756 requires(std::is_same_v<U, OpIndex>)
757 : constant_value_(), value_(index) {}
758
759 private:
760 std::optional<constant_type> constant_value_;
762};
763
764// Deduction guide for `ConstOrV`.
765template <typename T>
767
768template <>
770 V8_INLINE size_t operator()(OpIndex op) const { return op.hash(); }
771};
772
775 return base::hash_value(op.hash());
776}
777
778namespace detail {
779template <typename T, typename = void>
781 static constexpr bool exists = false;
782 using type = V<T>;
783};
784template <typename T>
785struct ConstOrVTypeHelper<T, std::void_t<ConstOrV<T>>> {
786 static constexpr bool exists = true;
788};
789} // namespace detail
790
791template <typename T>
793template <typename T>
795
796// `ShadowyOpIndex` is a wrapper around `OpIndex` that allows implicit
797// conversion to arbitrary `V<>`. This is required for generic code inside the
798// `Assembler` and `CopyingPhase`. Once implicit initialization of `V<>` from
799// `OpIndex` is disabled,
800//
801// OpIndex new_index = ...
802// ReduceWordUnary(new_index, ...)
803//
804// will no longer compile, because `ReduceWordUnary` expects a `V<Word>` input.
805// However,
806//
807// OpIndex new_index = ...
808// ReduceWordUnary(ShadowyOpIndex{new_index}, ...)
809//
810// will still compile. **Do not use ShadowyOpIndex directly** in any operations
811// or reducers.
812class ShadowyOpIndex : public OpIndex {
813 public:
814 explicit ShadowyOpIndex(OpIndex index) : OpIndex(index) {}
815
816 template <typename T>
817 operator V<T>() const { // NOLINT(runtime/explicit)
818 return V<T>::Cast(*this);
819 }
820};
821
822// Similarly to how `ShadowyOpIndex` is a wrapper around `OpIndex` that allows
823// arbitrary conversion to `V<>`, `ShadowyOpIndexVectorWrapper` is a wrapper
824// around `base::Vector<const OpIndex>` that allows implicit conversion to
825// `base::Vector<const V<U>>` for any `U`.
827 public:
828 template <typename T>
830 base::Vector<const V<T>> indices) // NOLINT(runtime/explicit)
831 : indices_(indices.data(), indices.size()) {}
833 base::Vector<const OpIndex> indices) // NOLINT(runtime/explicit)
834 : indices_(indices) {}
835 template <typename T>
837 base::Vector<V<T>> indices) // NOLINT(runtime/explicit)
838 : indices_(indices.data(), indices.size()) {}
840 base::Vector<OpIndex> indices) // NOLINT(runtime/explicit)
841 : indices_(indices) {}
842
843 operator base::Vector<const OpIndex>() const { // NOLINT(runtime/explicit)
844 return indices_;
845 }
846 template <typename U>
847 operator base::Vector<V<U>>() const { // NOLINT(runtime/explicit)
848 return base::Vector<V<U>>{indices_.data(), indices_.size()};
849 }
850 template <typename U>
851 operator base::Vector<const V<U>>() const { // NOLINT(runtime/explicit)
852 return {static_cast<const V<U>*>(indices_.data()), indices_.size()};
853 }
854
855 size_t size() const noexcept { return indices_.size(); }
856
857 private:
859};
860
861// `BlockIndex` is the index of a bound block.
862// A dominating block always has a smaller index.
863// It corresponds to the ordering of basic blocks in the operations buffer.
865 public:
866 explicit constexpr BlockIndex(uint32_t id) : id_(id) {}
867 constexpr BlockIndex() : id_(std::numeric_limits<uint32_t>::max()) {}
868
869 uint32_t id() const { return id_; }
870 bool valid() const { return *this != Invalid(); }
871
872 static constexpr BlockIndex Invalid() { return BlockIndex(); }
873
874 bool operator==(BlockIndex other) const { return id_ == other.id_; }
875 bool operator!=(BlockIndex other) const { return id_ != other.id_; }
876 bool operator<(BlockIndex other) const { return id_ < other.id_; }
877 bool operator>(BlockIndex other) const { return id_ > other.id_; }
878 bool operator<=(BlockIndex other) const { return id_ <= other.id_; }
879 bool operator>=(BlockIndex other) const { return id_ >= other.id_; }
880
881 template <typename H>
882 friend H AbslHashValue(H h, const BlockIndex& idx) {
883 return H::combine(std::move(h), idx.id_);
884 }
885
886 private:
887 uint32_t id_;
888};
889
890template <>
892 V8_INLINE size_t operator()(BlockIndex op) const { return op.id(); }
893};
894
896
897V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, BlockIndex b);
898
899#define DEFINE_STRONG_ORDERING_COMPARISON(lhs_type, rhs_type, lhs_access, \
900 rhs_access) \
901 V8_INLINE constexpr bool operator==(lhs_type l, rhs_type r) { \
902 return lhs_access == rhs_access; \
903 } \
904 V8_INLINE constexpr bool operator!=(lhs_type l, rhs_type r) { \
905 return lhs_access != rhs_access; \
906 } \
907 V8_INLINE constexpr bool operator<(lhs_type l, rhs_type r) { \
908 return lhs_access < rhs_access; \
909 } \
910 V8_INLINE constexpr bool operator<=(lhs_type l, rhs_type r) { \
911 return lhs_access <= rhs_access; \
912 } \
913 V8_INLINE constexpr bool operator>(lhs_type l, rhs_type r) { \
914 return lhs_access > rhs_access; \
915 } \
916 V8_INLINE constexpr bool operator>=(lhs_type l, rhs_type r) { \
917 return lhs_access >= rhs_access; \
918 }
920 l.value_or_invalid(), r.value_or_invalid())
924 l.value_or_invalid(), r)
925#undef DEFINE_STRONG_ORDERING_COMPARISON
926
927} // namespace v8::internal::compiler::turboshaft
928
929template <>
930struct std::hash<v8::internal::compiler::turboshaft::OpIndex> {
931 std::size_t operator()(
933 return index.hash();
934 }
935};
936
937#endif // V8_COMPILER_TURBOSHAFT_INDEX_H_
#define T
#define SLOW_DCHECK(condition)
Definition checks.h:21
#define SLOW_DCHECK_IMPLIES(v1, v2)
Definition checks.h:22
bool operator>(BlockIndex other) const
Definition index.h:877
static constexpr BlockIndex Invalid()
Definition index.h:872
bool operator!=(BlockIndex other) const
Definition index.h:875
bool operator==(BlockIndex other) const
Definition index.h:874
bool operator>=(BlockIndex other) const
Definition index.h:879
friend H AbslHashValue(H h, const BlockIndex &idx)
Definition index.h:882
bool operator<=(BlockIndex other) const
Definition index.h:878
bool operator<(BlockIndex other) const
Definition index.h:876
std::optional< constant_type > constant_value_
Definition index.h:760
static constexpr FloatRepresentation Float32()
static constexpr FloatRepresentation Float64()
constexpr bool operator<(OpIndex other) const
Definition index.h:111
constexpr bool operator>=(OpIndex other) const
Definition index.h:120
static constexpr OpIndex Invalid()
Definition index.h:88
static constexpr uint32_t kTurbofanNodeIdFlag
Definition index.h:153
constexpr bool operator==(OpIndex other) const
Definition index.h:105
friend H AbslHashValue(H h, const OpIndex &idx)
Definition index.h:156
constexpr uint32_t id() const
Definition index.h:61
OpIndex(const ConstOrV< T, C > &)
Definition index.h:55
constexpr bool operator>(OpIndex other) const
Definition index.h:114
static OpIndex EncodeTurbofanNodeId(uint32_t id)
Definition index.h:92
static constexpr uint32_t kGenerationMaskShift
Definition index.h:144
static constexpr uint32_t kGenerationMask
Definition index.h:145
constexpr bool operator!=(OpIndex other) const
Definition index.h:108
static constexpr uint32_t kUnmaskGenerationMask
Definition index.h:146
constexpr OpIndex(uint32_t offset)
Definition index.h:44
static constexpr OpIndex FromOffset(uint32_t offset)
Definition index.h:50
constexpr bool operator<=(OpIndex other) const
Definition index.h:117
friend H AbslHashValue(H h, const OptionalOpIndex &idx)
Definition index.h:185
static constexpr OptionalOpIndex Nullopt()
Definition index.h:171
static OptionalV< T > Cast(OptionalOpIndex index)
Definition index.h:689
static OptionalV< T > Cast(OptionalV< U > index)
Definition index.h:686
static constexpr bool implicitly_constructible_from
Definition index.h:659
constexpr V< T > value_or_invalid() const
Definition index.h:681
static constexpr RegisterRepresentation Compressed()
static constexpr RegisterRepresentation Simd128()
static constexpr RegisterRepresentation Word32()
static constexpr RegisterRepresentation Float64()
static constexpr RegisterRepresentation Float32()
static constexpr RegisterRepresentation Simd256()
static constexpr RegisterRepresentation Word64()
static constexpr RegisterRepresentation Tagged()
ShadowyOpIndexVectorWrapper(base::Vector< const V< T > > indices)
Definition index.h:829
ShadowyOpIndexVectorWrapper(base::Vector< const OpIndex > indices)
Definition index.h:832
ShadowyOpIndexVectorWrapper(base::Vector< V< T > > indices)
Definition index.h:836
ShadowyOpIndexVectorWrapper(base::Vector< OpIndex > indices)
Definition index.h:839
static constexpr auto rep
Definition index.h:618
static V< T > Cast(OpIndex index)
Definition index.h:635
static constexpr bool implicitly_constructible_from
Definition index.h:613
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:637
static V< T > Cast(V< U > index)
Definition index.h:632
#define DEFINE_STRONG_ORDERING_COMPARISON(lhs_type, rhs_type, lhs_access, rhs_access)
Definition index.h:899
ZoneVector< RpoNumber > & result
int r
Definition mul-fft.cc:298
STL namespace.
typename map< F, List >::type map_t
Definition list.h:180
typename element< List, Index >::type element_t
Definition list.h:173
V8_INLINE size_t hash_value(unsigned int v)
Definition hashing.h:205
ConstOrV(V< T >) -> ConstOrV< T >
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
bool operator==(const ControlState &lhs, const ControlState &rhs)
UnionOf< NumberOrString, BooleanOrNullOrUndefined > PlainPrimitive
Definition index.h:541
UnionOf< Boolean, Null, Undefined > BooleanOrNullOrUndefined
Definition index.h:539
UnionOf< Number, Undefined > NumberOrUndefined
Definition index.h:543
constexpr bool const_or_v_exists_v
Definition index.h:794
UnionOf< String, Null > StringOrNull
Definition index.h:542
constexpr nullrep_t nullrep
Definition index.h:197
WordWithBits< 64 > Word64
Definition index.h:224
V8_INLINE size_t hash_value(OpIndex op)
Definition index.h:773
std::conditional_t< Is64(), Word64, Word32 > WordPtr
Definition index.h:225
UnionOf< Number, String > NumberOrString
Definition index.h:540
UnionOf< BigInt, NonBigIntPrimitive > Primitive
Definition index.h:546
r value_or_invalid()) DEFINE_STRONG_ORDERING_COMPARISON(OptionalOpIndex
constexpr bool IsValidTypeFor(RegisterRepresentation repr)
Definition index.h:575
constexpr size_t kSlotsPerId
Definition index.h:31
UnionOf< FixedArray, FixedDoubleArray > AnyFixedArray
Definition index.h:544
OptionalV(V< T >) -> OptionalV< T >
typename detail::ConstOrVTypeHelper< T >::type maybe_const_or_v_t
Definition index.h:792
UnionOf< Symbol, PlainPrimitive > NonBigIntPrimitive
Definition index.h:545
bool operator!=(const ControlState &lhs, const ControlState &rhs)
constexpr int H
constexpr int kSimd128Size
Definition globals.h:706
static constexpr bool is_subtype_v
Definition tagged.h:121
constexpr int U
constexpr int kSimd256Size
Definition globals.h:709
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
Definition union.h:123
return value
Definition map-inl.h:893
constexpr bool Is64()
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
std::size_t operator()(const v8::internal::compiler::turboshaft::OpIndex &index) const
Definition index.h:931
base::tmp::element_t< to_list_t, Index > element_t
Definition index.h:254
std::conditional_t< base::tmp::contains_v< rep_types, nullrep_t >, nullrep_t, std::conditional_t< base::tmp::all_equal_v< rep_types >, typename v_traits< T >::rep_type, RegisterRepresentation > > rep_type
Definition index.h:472
base::tmp::map_t< to_rep_type, base::tmp::list< T, Ts... > > rep_types
Definition index.h:469
V8_INLINE size_t operator()(BlockIndex op) const
Definition index.h:892
V8_INLINE size_t operator()(OpIndex op) const
Definition index.h:770
static constexpr bool allows_representation(RegisterRepresentation)
Definition index.h:268
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:295
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:343
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:359
static constexpr bool allows_representation(RegisterRepresentation)
Definition index.h:281
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:375
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:391
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:406
static constexpr bool allows_representation(RegisterRepresentation)
Definition index.h:517
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:432
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:487
typename detail::RepresentationForUnion< UntaggedUnion< Ts... > >::rep_type rep_type
Definition index.h:483
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:311
static constexpr bool allows_representation(RegisterRepresentation maybe_allowed_rep)
Definition index.h:327
#define V8_INLINE
Definition v8config.h:500