v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-call-descriptors.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_RUNTIME_CALL_DESCRIPTORS_H_
6#define V8_COMPILER_TURBOSHAFT_RUNTIME_CALL_DESCRIPTORS_H_
7
11#include "src/runtime/runtime.h"
12
14
16 private:
17 template <typename Derived>
18 struct Descriptor {
19 static const TSCallDescriptor* Create(
20 Zone* zone, LazyDeoptOnThrow lazy_deopt_on_throw) {
21 DCHECK_IMPLIES(lazy_deopt_on_throw == LazyDeoptOnThrow::kYes,
22 Derived::kNeedsFrameState);
23 auto descriptor = Linkage::GetRuntimeCallDescriptor(
24 zone, Derived::kFunction,
25 std::tuple_size_v<typename Derived::arguments_t>,
26 Derived::kProperties,
27 Derived::kNeedsFrameState ? CallDescriptor::kNeedsFrameState
29#ifdef DEBUG
30 Derived::Verify(descriptor);
31#endif // DEBUG
32 CanThrow can_throw = (Derived::kProperties & Operator::kNoThrow)
35 return TSCallDescriptor::Create(descriptor, can_throw,
36 lazy_deopt_on_throw, zone);
37 }
38
39#ifdef DEBUG
40 static void Verify(const CallDescriptor* desc) {
41 using result_t = typename Derived::result_t;
42 using arguments_t = typename Derived::arguments_t;
43 if constexpr (std::is_same_v<result_t, void>) {
44 DCHECK_EQ(desc->ReturnCount(), 0);
45 } else {
46 DCHECK_EQ(desc->ReturnCount(), 1);
47 DCHECK(result_t::allows_representation(
49 desc->GetReturnType(0).representation())));
50 }
51 DCHECK_EQ(desc->NeedsFrameState(), Derived::kNeedsFrameState);
52 DCHECK_EQ(desc->properties(), Derived::kProperties);
53 constexpr int additional_stub_arguments =
54 3; // function id, argument count, context (or NoContextConstant)
55 DCHECK_EQ(desc->ParameterCount(),
56 std::tuple_size_v<arguments_t> + additional_stub_arguments);
57 DCHECK(VerifyArguments<arguments_t>(desc));
58 }
59
60 template <typename Arguments>
61 static bool VerifyArguments(const CallDescriptor* desc) {
62 return VerifyArgumentsImpl<Arguments>(
63 desc, std::make_index_sequence<std::tuple_size_v<Arguments>>());
64 }
65
66 private:
67 template <typename Arguments, size_t... Indices>
68 static bool VerifyArgumentsImpl(const CallDescriptor* desc,
69 std::index_sequence<Indices...>) {
70 return (std::tuple_element_t<Indices, Arguments>::allows_representation(
72 desc->GetParameterType(Indices).representation())) &&
73 ...);
74 }
75#endif // DEBUG
76 };
77
78 // TODO(nicohartmann@): Unfortunately, we cannot define builtins with
79 // void/never return types properly (e.g. in Torque), but they typically have
80 // a JSAny dummy return type. Use Void/Never sentinels to express that in
81 // Turboshaft's descriptors. We should find a better way to model this.
82 using Void = V<Any>;
83 using Never = V<Any>;
84
85 public:
86 struct Abort : public Descriptor<Abort> {
87 static constexpr auto kFunction = Runtime::kAbort;
88 using arguments_t = std::tuple<V<Smi>>;
90
91 static constexpr bool kNeedsFrameState = false;
94 };
95
96 struct BigIntUnaryOp : public Descriptor<BigIntUnaryOp> {
97 static constexpr auto kFunction = Runtime::kBigIntUnaryOp;
98 using arguments_t = std::tuple<V<BigInt>, V<Smi>>;
100
101 static constexpr bool kNeedsFrameState = false;
104 };
105
106 struct DateCurrentTime : public Descriptor<DateCurrentTime> {
107 static constexpr auto kFunction = Runtime::kDateCurrentTime;
108 using arguments_t = std::tuple<>;
110
111 static constexpr bool kNeedsFrameState = false;
114 };
115
116 struct DebugPrint : public Descriptor<DebugPrint> {
117 static constexpr auto kFunction = Runtime::kDebugPrint;
118 using arguments_t = std::tuple<V<Object>>;
119 using result_t = Void; // No actual result
120
121 static constexpr bool kNeedsFrameState = false;
124 };
125
126 struct StackGuard : public Descriptor<StackGuard> {
127 static constexpr auto kFunction = Runtime::kStackGuard;
128 using arguments_t = std::tuple<>;
130
131 static constexpr bool kNeedsFrameState = false;
132 // TODO(nicohartmann@): Verify this.
134 };
135
136 struct StackGuardWithGap : public Descriptor<StackGuardWithGap> {
137 static constexpr auto kFunction = Runtime::kStackGuardWithGap;
138 using arguments_t = std::tuple<V<Smi>>;
140
141 static constexpr bool kNeedsFrameState = true;
142 // TODO(nicohartmann@): Verify this.
144 };
145
147 : public Descriptor<HandleNoHeapWritesInterrupts> {
148 static constexpr auto kFunction = Runtime::kHandleNoHeapWritesInterrupts;
149 using arguments_t = std::tuple<>;
151
152 static constexpr bool kNeedsFrameState = true;
154 };
155
156 struct PropagateException : public Descriptor<PropagateException> {
157 static constexpr auto kFunction = Runtime::kPropagateException;
158 using arguments_t = std::tuple<>;
160
161 static constexpr bool kNeedsFrameState = true;
163 };
164
165 struct ReThrow : public Descriptor<ReThrow> {
166 static constexpr auto kFunction = Runtime::kReThrow;
167 using arguments_t = std::tuple<V<Object>>;
169
170 static constexpr bool kNeedsFrameState = false;
172 };
173
174 struct StringCharCodeAt : public Descriptor<StringCharCodeAt> {
175 static constexpr auto kFunction = Runtime::kStringCharCodeAt;
176 using arguments_t = std::tuple<V<String>, V<Number>>;
178
179 static constexpr bool kNeedsFrameState = false;
182 };
183
184#ifdef V8_INTL_SUPPORT
185 struct StringToUpperCaseIntl : public Descriptor<StringToUpperCaseIntl> {
186 static constexpr auto kFunction = Runtime::kStringToUpperCaseIntl;
187 using arguments_t = std::tuple<V<String>>;
188 using result_t = V<String>;
189
190 static constexpr bool kNeedsFrameState = false;
191 static constexpr Operator::Properties kProperties =
192 Operator::kNoDeopt | Operator::kNoThrow;
193 };
194#endif // V8_INTL_SUPPORT
195
196 struct SymbolDescriptiveString : public Descriptor<SymbolDescriptiveString> {
197 static constexpr auto kFunction = Runtime::kSymbolDescriptiveString;
198 using arguments_t = std::tuple<V<Symbol>>;
200
201 static constexpr bool kNeedsFrameState = true;
203 };
204
205 struct TerminateExecution : public Descriptor<TerminateExecution> {
206 static constexpr auto kFunction = Runtime::kTerminateExecution;
207 using arguments_t = std::tuple<>;
209
210 static constexpr bool kNeedsFrameState = true;
212 };
213
214 struct TransitionElementsKind : public Descriptor<TransitionElementsKind> {
215 static constexpr auto kFunction = Runtime::kTransitionElementsKind;
216 using arguments_t = std::tuple<V<HeapObject>, V<Map>>;
218
219 static constexpr bool kNeedsFrameState = false;
222 };
223
224 struct TryMigrateInstance : public Descriptor<TryMigrateInstance> {
225 static constexpr auto kFunction = Runtime::kTryMigrateInstance;
226 using arguments_t = std::tuple<V<HeapObject>>;
228
229 static constexpr bool kNeedsFrameState = false;
232 };
233
235 : public Descriptor<TryMigrateInstanceAndMarkMapAsMigrationTarget> {
236 static constexpr auto kFunction =
237 Runtime::kTryMigrateInstanceAndMarkMapAsMigrationTarget;
238 using arguments_t = std::tuple<V<HeapObject>>;
240
241 static constexpr bool kNeedsFrameState = false;
244 };
245
247 : public Descriptor<ThrowAccessedUninitializedVariable> {
248 static constexpr auto kFunction =
249 Runtime::kThrowAccessedUninitializedVariable;
250 using arguments_t = std::tuple<V<Object>>;
251 // Doesn't actually return something, but the actual runtime call descriptor
252 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
254
255 static constexpr bool kNeedsFrameState = true;
257 };
258
260 : public Descriptor<ThrowConstructorReturnedNonObject> {
261 static constexpr auto kFunction =
262 Runtime::kThrowConstructorReturnedNonObject;
263 using arguments_t = std::tuple<>;
264 // Doesn't actually return something, but the actual runtime call descriptor
265 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
267
268 static constexpr bool kNeedsFrameState = true;
270 };
271
273 : public Descriptor<ThrowNotSuperConstructor> {
274 static constexpr auto kFunction = Runtime::kThrowNotSuperConstructor;
275 using arguments_t = std::tuple<V<Object>, V<Object>>;
276 // Doesn't actually return something, but the actual runtime call descriptor
277 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
279
280 static constexpr bool kNeedsFrameState = true;
282 };
283
285 : public Descriptor<ThrowSuperAlreadyCalledError> {
286 static constexpr auto kFunction = Runtime::kThrowSuperAlreadyCalledError;
287 using arguments_t = std::tuple<>;
288 // Doesn't actually return something, but the actual runtime call descriptor
289 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
291
292 static constexpr bool kNeedsFrameState = true;
294 };
295
296 struct ThrowSuperNotCalled : public Descriptor<ThrowSuperNotCalled> {
297 static constexpr auto kFunction = Runtime::kThrowSuperNotCalled;
298 using arguments_t = std::tuple<>;
299 // Doesn't actually return something, but the actual runtime call descriptor
300 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
302
303 static constexpr bool kNeedsFrameState = true;
305 };
306
307 struct ThrowCalledNonCallable : public Descriptor<ThrowCalledNonCallable> {
308 static constexpr auto kFunction = Runtime::kThrowCalledNonCallable;
309 using arguments_t = std::tuple<V<Object>>;
310 // Doesn't actually return something, but the actual runtime call descriptor
311 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
313
314 static constexpr bool kNeedsFrameState = true;
316 };
317
319 : public Descriptor<ThrowInvalidStringLength> {
320 static constexpr auto kFunction = Runtime::kThrowInvalidStringLength;
321 using arguments_t = std::tuple<>;
322 // Doesn't actually return something, but the actual runtime call descriptor
323 // (returned by Linkage::GetRuntimeCallDescriptor) returns 1 instead of 0.
325
326 static constexpr bool kNeedsFrameState = true;
328 };
329
330 struct NewClosure : public Descriptor<NewClosure> {
331 static constexpr auto kFunction = Runtime::kNewClosure;
332 using arguments_t = std::tuple<V<SharedFunctionInfo>, V<FeedbackCell>>;
334
335 static constexpr bool kNeedsFrameState = false;
337 };
338
339 struct NewClosure_Tenured : public Descriptor<NewClosure_Tenured> {
340 static constexpr auto kFunction = Runtime::kNewClosure_Tenured;
341 using arguments_t = std::tuple<V<SharedFunctionInfo>, V<FeedbackCell>>;
343
344 static constexpr bool kNeedsFrameState = false;
346 };
347
348 struct HasInPrototypeChain : public Descriptor<HasInPrototypeChain> {
349 static constexpr auto kFunction = Runtime::kHasInPrototypeChain;
350 using arguments_t = std::tuple<V<Object>, V<HeapObject>>;
352
353 static constexpr bool kNeedsFrameState = true;
355 };
356};
357
358} // namespace v8::internal::compiler::turboshaft
359
360#endif // V8_COMPILER_TURBOSHAFT_RUNTIME_CALL_DESCRIPTORS_H_
static CallDescriptor * GetRuntimeCallDescriptor(Zone *zone, Runtime::FunctionId function, int js_parameter_count, Operator::Properties properties, CallDescriptor::Flags flags, LazyDeoptOnThrow lazy_deopt_on_throw=LazyDeoptOnThrow::kNo)
Definition linkage.cc:426
static constexpr RegisterRepresentation FromMachineRepresentation(MachineRepresentation rep)
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
static const TSCallDescriptor * Create(Zone *zone, LazyDeoptOnThrow lazy_deopt_on_throw)
std::tuple< V< SharedFunctionInfo >, V< FeedbackCell > > arguments_t
static const TSCallDescriptor * Create(const CallDescriptor *descriptor, CanThrow can_throw, LazyDeoptOnThrow lazy_deopt_on_throw, Zone *graph_zone, const JSWasmCallParameters *js_wasm_call_parameters=nullptr)