v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
union.h
Go to the documentation of this file.
1// Copyright 2024 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_OBJECTS_UNION_H_
6#define V8_OBJECTS_UNION_H_
7
10
11namespace v8::internal {
12
13// Union<Ts...> represents a union of multiple V8 types.
14//
15// Unions are required to be non-nested (i.e. no unions of unions), and to
16// have each type only once. The UnionOf<Ts...> helper can be used to flatten
17// nested unions and remove duplicates.
18//
19// Inheritance from Unions is forbidden because it messes with `is_subtype`
20// checking.
21template <typename... Ts>
22class Union;
23
24// is_union<T> is a type trait that returns true if T is a union.
25template <typename... Ts>
26struct is_union : public std::false_type {};
27template <typename... Ts>
28struct is_union<Union<Ts...>> : public std::true_type {};
29template <typename... Ts>
30static constexpr bool is_union_v = is_union<Ts...>::value;
31
32namespace detail {
33
34template <typename Accumulator, typename TWithout, typename... InputTypes>
36
37// Base case: No input types, return the accumulated types.
38template <typename... OutputTs, typename TWithout>
39struct UnionWithoutHelper<Union<OutputTs...>, TWithout> {
40 using type = Union<OutputTs...>;
41};
42
43// Recursive case: Found Head matching TWithout, drop it and accumulate the
44// remainder.
45template <typename... OutputTs, typename TWithout, typename... Ts>
46struct UnionWithoutHelper<Union<OutputTs...>, TWithout, TWithout, Ts...> {
47 using type = Union<OutputTs..., Ts...>;
48};
49
50// Recursive case: Non-matching input, accumulate and continue.
51template <typename... OutputTs, typename TWithout, typename Head,
52 typename... Ts>
53struct UnionWithoutHelper<Union<OutputTs...>, TWithout, Head, Ts...> {
54 // Don't accumulate duplicate types.
55 using type = typename UnionWithoutHelper<Union<OutputTs..., Head>, TWithout,
56 Ts...>::type;
57};
58
59} // namespace detail
60
61template <typename... Ts>
62class Union final : public AllStatic {
63 public:
64 static_assert((!is_union_v<Ts> && ...),
65 "Cannot have a union of unions -- use the UnionOf<T...> helper "
66 "to flatten nested unions");
67 static_assert(
68 (base::has_type_v<Ts, Ts...> && ...),
69 "Unions should have each type only once -- use the UnionOf<T...> "
70 "helper to deduplicate unions");
71
72 template <typename U>
74};
75
76namespace detail {
77
78template <typename Accumulator, typename... InputTypes>
80
81// Base case: No input types, return the accumulated types.
82template <typename... OutputTs>
83struct FlattenUnionHelper<Union<OutputTs...>> {
84 using type = Union<OutputTs...>;
85};
86
87// Recursive case: Non-union input, accumulate and continue.
88template <typename... OutputTs, typename Head, typename... Ts>
89struct FlattenUnionHelper<Union<OutputTs...>, Head, Ts...> {
90 // Don't accumulate duplicate types.
91 using type = std::conditional_t<
92 base::has_type_v<Head, OutputTs...>,
93 typename FlattenUnionHelper<Union<OutputTs...>, Ts...>::type,
94 typename FlattenUnionHelper<Union<OutputTs..., Head>, Ts...>::type>;
95};
96
97// Recursive case: Smi input, normalize to always be the first element.
98//
99// This is a small optimization to try reduce the number of template
100// specializations -- ideally we would fully sort the types but this probably
101// costs more templates than it saves.
102template <typename... OutputTs, typename... Ts>
103struct FlattenUnionHelper<Union<OutputTs...>, Smi, Ts...> {
104 // Don't accumulate duplicate types.
105 using type = std::conditional_t<
106 base::has_type_v<Smi, OutputTs...>,
107 typename FlattenUnionHelper<Union<OutputTs...>, Ts...>::type,
108 typename FlattenUnionHelper<Union<Smi, OutputTs...>, Ts...>::type>;
109};
110
111// Recursive case: Union input, flatten and continue.
112template <typename... OutputTs, typename... HeadTs, typename... Ts>
113struct FlattenUnionHelper<Union<OutputTs...>, Union<HeadTs...>, Ts...> {
114 using type =
115 typename FlattenUnionHelper<Union<OutputTs...>, HeadTs..., Ts...>::type;
116};
117
118} // namespace detail
119
120// UnionOf<Ts...> is a helper that returns a union of multiple V8 types,
121// flattening any nested unions and removing duplicate types.
122template <typename... Ts>
124
125// Unions of unions are flattened.
126static_assert(std::is_same_v<Union<Smi, HeapObject>,
128// Unions with duplicates are deduplicated.
129static_assert(std::is_same_v<Union<Smi, HeapObject>,
131// Unions with Smis are normalized to have the Smi be the first element.
132static_assert(std::is_same_v<Union<Smi, HeapObject>, UnionOf<HeapObject, Smi>>);
133
134// Union::Without matches expectations.
135static_assert(
136 std::is_same_v<Union<Smi, HeapObject>::Without<Smi>, Union<HeapObject>>);
137static_assert(std::is_same_v<JSAny::Without<Smi>, JSAnyNotSmi>);
138static_assert(
139 std::is_same_v<JSAny::Without<Smi>::Without<HeapNumber>, JSAnyNotNumber>);
140
141// Union::Without that doesn't have a match is a no-op
142static_assert(std::is_same_v<Union<Smi, HeapObject>::Without<HeapNumber>,
144
145} // namespace v8::internal
146
147#endif // V8_OBJECTS_UNION_H_
typename detail::UnionWithoutHelper< Union<>, U, Ts... >::type Without
Definition union.h:73
constexpr bool has_type_v
V8_EXPORT_PRIVATE TypeInModule Union(ValueType type1, ValueType type2, const WasmModule *module1, const WasmModule *module2)
static constexpr bool is_union_v
Definition union.h:30
constexpr int U
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
Definition union.h:123
return value
Definition map-inl.h:893
std::conditional_t< base::has_type_v< Head, OutputTs... >, typename FlattenUnionHelper< Union< OutputTs... >, Ts... >::type, typename FlattenUnionHelper< Union< OutputTs..., Head >, Ts... >::type > type
Definition union.h:91
std::conditional_t< base::has_type_v< Smi, OutputTs... >, typename FlattenUnionHelper< Union< OutputTs... >, Ts... >::type, typename FlattenUnionHelper< Union< Smi, OutputTs... >, Ts... >::type > type
Definition union.h:105
typename FlattenUnionHelper< Union< OutputTs... >, HeadTs..., Ts... >::type type
Definition union.h:114
typename UnionWithoutHelper< Union< OutputTs..., Head >, TWithout, Ts... >::type type
Definition union.h:55
wasm::ValueType type