v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
utils.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_UTILS_H_
6#define V8_COMPILER_TURBOSHAFT_UTILS_H_
7
8#include <iostream>
9#include <limits>
10#include <tuple>
11
12#include "src/base/logging.h"
13#include "src/base/macros.h"
14
16
17template <class... Ts>
18struct any_of : std::tuple<const Ts&...> {
19 explicit any_of(const Ts&... args) : std::tuple<const Ts&...>(args...) {}
20
21 template <class T, size_t... indices>
22 bool Contains(const T& value, std::index_sequence<indices...>) {
23 return ((value == std::get<indices>(*this)) || ...);
24 }
25
26 template <size_t... indices>
27 std::ostream& PrintTo(std::ostream& os, std::index_sequence<indices...>) {
28 bool first = true;
29 os << "any_of(";
30 (((first ? (first = false, os) : os << ", "),
31 os << base::PrintCheckOperand(std::get<indices>(*this))),
32 ...);
33 return os << ")";
34 }
35};
36template <class... Args>
37any_of(const Args&...) -> any_of<Args...>;
38
39template <class T, class... Ts>
40bool operator==(const T& value, any_of<Ts...> options) {
41 return options.Contains(value, std::index_sequence_for<Ts...>{});
42}
43
44template <class... Ts>
45std::ostream& operator<<(std::ostream& os, any_of<Ts...> any) {
46 return any.PrintTo(os, std::index_sequence_for<Ts...>{});
47}
48
49template <class... Ts>
50struct all_of : std::tuple<const Ts&...> {
51 explicit all_of(const Ts&... args) : std::tuple<const Ts&...>(args...) {}
52
53 template <class T, size_t... indices>
54 bool AllEqualTo(const T& value, std::index_sequence<indices...>) {
55 return ((value == std::get<indices>(*this)) && ...);
56 }
57
58 template <size_t... indices>
59 std::ostream& PrintTo(std::ostream& os, std::index_sequence<indices...>) {
60 bool first = true;
61 os << "all_of(";
62 (((first ? (first = false, os) : os << ", "),
63 os << base::PrintCheckOperand(std::get<indices>(*this))),
64 ...);
65 return os << ")";
66 }
67};
68template <class... Args>
69all_of(const Args&...) -> all_of<Args...>;
70
71template <class T, class... Ts>
72bool operator==(all_of<Ts...> values, const T& target) {
73 return values.AllEqualTo(target, std::index_sequence_for<Ts...>{});
74}
75
76template <class... Ts>
77std::ostream& operator<<(std::ostream& os, all_of<Ts...> all) {
78 return all.PrintTo(os, std::index_sequence_for<Ts...>{});
79}
80
81#ifdef DEBUG
83#else
84V8_EXPORT_PRIVATE inline bool ShouldSkipOptimizationStep() { return false; }
85#endif
86
87// Set `*ptr` to `new_value` while the scope is active, reset to the previous
88// value upon destruction.
89template <class T>
91 public:
92 ScopedModification(T* ptr, T new_value)
93 : ptr_(ptr), old_value_(std::move(*ptr)) {
94 *ptr = std::move(new_value);
95 }
96
97 ~ScopedModification() { *ptr_ = std::move(old_value_); }
98
99 const T& old_value() const { return old_value_; }
100
101 private:
104};
105
106// The `multi`-switch mechanism helps to switch on multiple values at the same
107// time. Example:
108//
109// switch (multi(change.from, change.to)) {
110// case multi(Word32(), Float32()): ...
111// case multi(Word32(), Float64()): ...
112// case multi(Word64(), Float32()): ...
113// case multi(Word64(), Float64()): ...
114// ...
115// }
116//
117// This works for an arbitrary number of dimensions and arbitrary types as long
118// as they can be encoded into an integral value and their combination fits into
119// a uint64_t. For types to be used, they need to provide a specialization of
120// MultiSwitch<T> with this signature:
121//
122// template<>
123// struct MultiSwitch<T> {
124// static constexpr uint64_t max_value = ...
125// static constexpr uint64_t encode(T value) { ... }
126// };
127//
128// For `max_value` choose a value that is larger than all encoded values. Choose
129// this as small as possible to make jump tables more dense. If a type's value
130// count is somewhat close to a multiple of two, consider using this, as this
131// might lead to slightly faster encoding. The encoding follows this formula:
132//
133// multi(v1, v2, v3) =
134// let t1 = MultiSwitch<T3>::encode(v3) in
135// let t2 = (t1 * MultiSwitch<T2>::max_value)
136// + MultiSwitch<T2>::encode(v2) in
137// (t2 * MultiSwitch<T1>::max_value) + MultiSwitch<T1>::encode(v1)
138//
139// For integral types (like enums), use
140//
141// DEFINE_MULTI_SWITCH_INTEGRAL(MyType, MaxValue)
142//
143template <typename T, typename Enable = void>
145
146template <typename T, uint64_t MaxValue>
148 static constexpr uint64_t max_value = MaxValue;
149 static constexpr uint64_t encode(T value) {
150 const uint64_t v = static_cast<uint64_t>(value);
152 return v;
153 }
154};
155
156#define DEFINE_MULTI_SWITCH_INTEGRAL(name, max_value) \
157 template <> \
158 struct MultiSwitch<name> : MultiSwitchIntegral<name, max_value> {};
159
160namespace detail {
161template <typename T>
162constexpr uint64_t multi_encode(const T& value) {
163 return MultiSwitch<T>::encode(value);
164}
165
166template <typename Head, typename Next, typename... Rest>
167constexpr uint64_t multi_encode(const Head& head, const Next& next,
168 const Rest&... rest) {
169 uint64_t v = multi_encode(next, rest...);
170 DCHECK_LT(
171 v, std::numeric_limits<uint64_t>::max() / MultiSwitch<Head>::max_value);
173}
174} // namespace detail
175
176template <typename... Ts>
177inline constexpr uint64_t multi(const Ts&... values) {
178 return detail::multi_encode(values...);
179}
180
182
183} // namespace v8::internal::compiler::turboshaft
184
185#endif // V8_COMPILER_TURBOSHAFT_UTILS_H_
#define T
#define DEFINE_MULTI_SWITCH_INTEGRAL(name, max_value)
Definition utils.h:156
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
STL namespace.
constexpr uint64_t multi_encode(const T &value)
Definition utils.h:162
constexpr uint64_t multi(const Ts &... values)
Definition utils.h:177
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
bool operator==(const ControlState &lhs, const ControlState &rhs)
any_of(const Args &...) -> any_of< Args... >
all_of(const Args &...) -> all_of< Args... >
V8_EXPORT_PRIVATE bool ShouldSkipOptimizationStep()
Definition utils.h:84
return value
Definition map-inl.h:893
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define V8_EXPORT_PRIVATE
Definition macros.h:460
static constexpr uint64_t encode(T value)
Definition utils.h:149
std::ostream & PrintTo(std::ostream &os, std::index_sequence< indices... >)
Definition utils.h:59
bool AllEqualTo(const T &value, std::index_sequence< indices... >)
Definition utils.h:54
bool Contains(const T &value, std::index_sequence< indices... >)
Definition utils.h:22
std::ostream & PrintTo(std::ostream &os, std::index_sequence< indices... >)
Definition utils.h:27