1// Copyright 2012 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#include "src/interface-descriptors.h"
6
7#include "src/macro-assembler.h"
8
9namespace v8 {
10namespace internal {
11
12void CallInterfaceDescriptorData::InitializePlatformSpecific(
13 int register_parameter_count, const Register* registers) {
14 DCHECK(!IsInitializedPlatformIndependent());
15
16 register_param_count_ = register_parameter_count;
17
18 // UBSan doesn't like creating zero-length arrays.
19 if (register_parameter_count == 0) return;
20
21 // InterfaceDescriptor owns a copy of the registers array.
22 register_params_ = NewArray<Register>(register_parameter_count, no_reg);
23 for (int i = 0; i < register_parameter_count; i++) {
24 // The value of the root register must be reserved, thus any uses
25 // within the calling convention are disallowed.
26 DCHECK_NE(registers[i], kRootRegister);
27 register_params_[i] = registers[i];
28 }
29}
30
31void CallInterfaceDescriptorData::InitializePlatformIndependent(
32 Flags flags, int return_count, int parameter_count,
33 const MachineType* machine_types, int machine_types_length) {
34 DCHECK(IsInitializedPlatformSpecific());
35
36 flags_ = flags;
37 return_count_ = return_count;
38 param_count_ = parameter_count;
39 const int types_length = return_count_ + param_count_;
40
41 // Machine types are either fully initialized or null.
42 if (machine_types == nullptr) {
43 machine_types_ =
44 NewArray<MachineType>(types_length, MachineType::AnyTagged());
45 } else {
46 DCHECK_EQ(machine_types_length, types_length);
47 machine_types_ = NewArray<MachineType>(types_length);
48 for (int i = 0; i < types_length; i++) machine_types_[i] = machine_types[i];
49 }
50
51 if (!(flags_ & kNoStackScan)) DCHECK(AllStackParametersAreTagged());
52}
53
54#ifdef DEBUG
55bool CallInterfaceDescriptorData::AllStackParametersAreTagged() const {
56 DCHECK(IsInitialized());
57 const int types_length = return_count_ + param_count_;
58 const int first_stack_param = return_count_ + register_param_count_;
59 for (int i = first_stack_param; i < types_length; i++) {
60 if (!machine_types_[i].IsTagged()) return false;
61 }
62 return true;
63}
64#endif // DEBUG
65
66void CallInterfaceDescriptorData::Reset() {
67 delete[] machine_types_;
68 machine_types_ = nullptr;
69 delete[] register_params_;
70 register_params_ = nullptr;
71}
72
73// static
74CallInterfaceDescriptorData
75 CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
76
77void CallDescriptors::InitializeOncePerProcess() {
78#define INTERFACE_DESCRIPTOR(name, ...) \
79 name##Descriptor().Initialize(&call_descriptor_data_[CallDescriptors::name]);
80 INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
81#undef INTERFACE_DESCRIPTOR
82
83 DCHECK(ContextOnlyDescriptor{}.HasContextParameter());
84 DCHECK(!NoContextDescriptor{}.HasContextParameter());
85 DCHECK(!AllocateDescriptor{}.HasContextParameter());
86 DCHECK(!AllocateHeapNumberDescriptor{}.HasContextParameter());
87 DCHECK(!AbortDescriptor{}.HasContextParameter());
88}
89
90void CallDescriptors::TearDown() {
91 for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
92 data.Reset();
93 }
94}
95
96void CallInterfaceDescriptor::JSDefaultInitializePlatformSpecific(
97 CallInterfaceDescriptorData* data, int non_js_register_parameter_count) {
98 DCHECK_LE(static_cast<unsigned>(non_js_register_parameter_count), 1);
99
100 // 3 is for kTarget, kNewTarget and kActualArgumentsCount
101 int register_parameter_count = 3 + non_js_register_parameter_count;
102
103 DCHECK(!AreAliased(
104 kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
105 kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register));
106
107 const Register default_js_stub_registers[] = {
108 kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
109 kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register};
110
111 CHECK_LE(static_cast<size_t>(register_parameter_count),
112 arraysize(default_js_stub_registers));
113 data->InitializePlatformSpecific(register_parameter_count,
114 default_js_stub_registers);
115}
116
117const char* CallInterfaceDescriptor::DebugName() const {
118 CallDescriptors::Key key = CallDescriptors::GetKey(data_);
119 switch (key) {
120#define DEF_CASE(name, ...) \
121 case CallDescriptors::name: \
122 return #name " Descriptor";
123 INTERFACE_DESCRIPTOR_LIST(DEF_CASE)
124#undef DEF_CASE
125 case CallDescriptors::NUMBER_OF_DESCRIPTORS:
126 break;
127 }
128 return "";
129}
130
131#if !defined(V8_TARGET_ARCH_MIPS) && !defined(V8_TARGET_ARCH_MIPS64)
132bool CallInterfaceDescriptor::IsValidFloatParameterRegister(Register reg) {
133 return true;
134}
135#endif
136
137void VoidDescriptor::InitializePlatformSpecific(
138 CallInterfaceDescriptorData* data) {
139 data->InitializePlatformSpecific(0, nullptr);
140}
141
142void AllocateDescriptor::InitializePlatformSpecific(
143 CallInterfaceDescriptorData* data) {
144 Register registers[] = {kAllocateSizeRegister};
145 data->InitializePlatformSpecific(arraysize(registers), registers);
146}
147
148void CEntry1ArgvOnStackDescriptor::InitializePlatformSpecific(
149 CallInterfaceDescriptorData* data) {
150 Register registers[] = {kRuntimeCallArgCountRegister,
151 kRuntimeCallFunctionRegister};
152 data->InitializePlatformSpecific(arraysize(registers), registers);
153}
154
155namespace {
156
157void InterpreterCEntryDescriptor_InitializePlatformSpecific(
158 CallInterfaceDescriptorData* data) {
159 Register registers[] = {kRuntimeCallArgCountRegister,
160 kRuntimeCallArgvRegister,
161 kRuntimeCallFunctionRegister};
162 data->InitializePlatformSpecific(arraysize(registers), registers);
163}
164
165} // namespace
166
167void InterpreterCEntry1Descriptor::InitializePlatformSpecific(
168 CallInterfaceDescriptorData* data) {
169 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
170}
171
172void InterpreterCEntry2Descriptor::InitializePlatformSpecific(
173 CallInterfaceDescriptorData* data) {
174 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
175}
176
177void FastNewFunctionContextDescriptor::InitializePlatformSpecific(
178 CallInterfaceDescriptorData* data) {
179 Register registers[] = {ScopeInfoRegister(), SlotsRegister()};
180 data->InitializePlatformSpecific(arraysize(registers), registers);
181}
182
183void FastNewObjectDescriptor::InitializePlatformSpecific(
184 CallInterfaceDescriptorData* data) {
185 Register registers[] = {TargetRegister(), NewTargetRegister()};
186 data->InitializePlatformSpecific(arraysize(registers), registers);
187}
188
189const Register FastNewObjectDescriptor::TargetRegister() {
190 return kJSFunctionRegister;
191}
192
193const Register FastNewObjectDescriptor::NewTargetRegister() {
194 return kJavaScriptCallNewTargetRegister;
195}
196
197
198void LoadDescriptor::InitializePlatformSpecific(
199 CallInterfaceDescriptorData* data) {
200 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
201 data->InitializePlatformSpecific(arraysize(registers), registers);
202}
203
204void LoadGlobalDescriptor::InitializePlatformSpecific(
205 CallInterfaceDescriptorData* data) {
206 Register registers[] = {NameRegister(), SlotRegister()};
207 data->InitializePlatformSpecific(arraysize(registers), registers);
208}
209
210void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
211 CallInterfaceDescriptorData* data) {
212 Register registers[] = {NameRegister(), SlotRegister(), VectorRegister()};
213 data->InitializePlatformSpecific(arraysize(registers), registers);
214}
215
216void StoreGlobalDescriptor::InitializePlatformSpecific(
217 CallInterfaceDescriptorData* data) {
218 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister()};
219
220 int len = arraysize(registers) - kStackArgumentsCount;
221 data->InitializePlatformSpecific(len, registers);
222}
223
224void StoreGlobalWithVectorDescriptor::InitializePlatformSpecific(
225 CallInterfaceDescriptorData* data) {
226 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister(),
227 VectorRegister()};
228 int len = arraysize(registers) - kStackArgumentsCount;
229 data->InitializePlatformSpecific(len, registers);
230}
231
232void StoreDescriptor::InitializePlatformSpecific(
233 CallInterfaceDescriptorData* data) {
234 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
235 SlotRegister()};
236
237 int len = arraysize(registers) - kStackArgumentsCount;
238 data->InitializePlatformSpecific(len, registers);
239}
240
241void StoreTransitionDescriptor::InitializePlatformSpecific(
242 CallInterfaceDescriptorData* data) {
243 Register registers[] = {
244 ReceiverRegister(), NameRegister(), MapRegister(),
245 ValueRegister(), SlotRegister(), VectorRegister(),
246 };
247 int len = arraysize(registers) - kStackArgumentsCount;
248 data->InitializePlatformSpecific(len, registers);
249}
250
251void StringAtDescriptor::InitializePlatformSpecific(
252 CallInterfaceDescriptorData* data) {
253 DefaultInitializePlatformSpecific(data, kParameterCount);
254}
255
256void StringSubstringDescriptor::InitializePlatformSpecific(
257 CallInterfaceDescriptorData* data) {
258 DefaultInitializePlatformSpecific(data, kParameterCount);
259}
260
261void TypeConversionDescriptor::InitializePlatformSpecific(
262 CallInterfaceDescriptorData* data) {
263 Register registers[] = {ArgumentRegister()};
264 data->InitializePlatformSpecific(arraysize(registers), registers);
265}
266
267void TypeConversionStackParameterDescriptor::InitializePlatformSpecific(
268 CallInterfaceDescriptorData* data) {
269 data->InitializePlatformSpecific(0, nullptr);
270}
271
272void AsyncFunctionStackParameterDescriptor::InitializePlatformSpecific(
273 CallInterfaceDescriptorData* data) {
274 data->InitializePlatformSpecific(0, nullptr);
275}
276
277void LoadWithVectorDescriptor::InitializePlatformSpecific(
278 CallInterfaceDescriptorData* data) {
279 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
280 VectorRegister()};
281 // TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
282 // to allow no_reg entries.
283 // DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), SlotRegister(),
284 // VectorRegister(), kRootRegister));
285 int len = arraysize(registers) - kStackArgumentsCount;
286 data->InitializePlatformSpecific(len, registers);
287}
288
289void StoreWithVectorDescriptor::InitializePlatformSpecific(
290 CallInterfaceDescriptorData* data) {
291 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
292 SlotRegister(), VectorRegister()};
293 // TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
294 // to allow no_reg entries.
295 // DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), kRootRegister));
296 int len = arraysize(registers) - kStackArgumentsCount;
297 data->InitializePlatformSpecific(len, registers);
298}
299
300const Register ApiGetterDescriptor::ReceiverRegister() {
301 return LoadDescriptor::ReceiverRegister();
302}
303
304void ApiGetterDescriptor::InitializePlatformSpecific(
305 CallInterfaceDescriptorData* data) {
306 Register registers[] = {ReceiverRegister(), HolderRegister(),
307 CallbackRegister()};
308 data->InitializePlatformSpecific(arraysize(registers), registers);
309}
310
311void ContextOnlyDescriptor::InitializePlatformSpecific(
312 CallInterfaceDescriptorData* data) {
313 data->InitializePlatformSpecific(0, nullptr);
314}
315
316void NoContextDescriptor::InitializePlatformSpecific(
317 CallInterfaceDescriptorData* data) {
318 data->InitializePlatformSpecific(0, nullptr);
319}
320
321void GrowArrayElementsDescriptor::InitializePlatformSpecific(
322 CallInterfaceDescriptorData* data) {
323 Register registers[] = {ObjectRegister(), KeyRegister()};
324 data->InitializePlatformSpecific(arraysize(registers), registers);
325}
326
327void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
328 CallInterfaceDescriptorData* data) {
329 DefaultInitializePlatformSpecific(data, kParameterCount);
330}
331
332void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
333 CallInterfaceDescriptorData* data) {
334 // This descriptor must use the same set of registers as the
335 // ArrayNArgumentsConstructorDescriptor.
336 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
337}
338
339void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
340 CallInterfaceDescriptorData* data) {
341 // This descriptor must use the same set of registers as the
342 // ArrayNArgumentsConstructorDescriptor.
343 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
344}
345
346void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
347 CallInterfaceDescriptorData* data) {
348 // Keep the arguments on the same registers as they were in
349 // ArrayConstructorDescriptor to avoid unnecessary register moves.
350 // kFunction, kAllocationSite, kActualArgumentsCount
351 Register registers[] = {kJavaScriptCallTargetRegister,
352 kJavaScriptCallExtraArg1Register,
353 kJavaScriptCallArgCountRegister};
354 data->InitializePlatformSpecific(arraysize(registers), registers);
355}
356
357void WasmMemoryGrowDescriptor::InitializePlatformSpecific(
358 CallInterfaceDescriptorData* data) {
359 DefaultInitializePlatformSpecific(data, kParameterCount);
360}
361
362void WasmTableGetDescriptor::InitializePlatformSpecific(
363 CallInterfaceDescriptorData* data) {
364 DefaultInitializePlatformSpecific(data, kParameterCount);
365}
366
367void WasmTableSetDescriptor::InitializePlatformSpecific(
368 CallInterfaceDescriptorData* data) {
369 DefaultInitializePlatformSpecific(data, kParameterCount);
370}
371
372void WasmThrowDescriptor::InitializePlatformSpecific(
373 CallInterfaceDescriptorData* data) {
374 DefaultInitializePlatformSpecific(data, kParameterCount);
375}
376
377void WasmAtomicNotifyDescriptor::InitializePlatformSpecific(
378 CallInterfaceDescriptorData* data) {
379 DefaultInitializePlatformSpecific(data, kParameterCount);
380}
381
382#if !defined(V8_TARGET_ARCH_MIPS) && !defined(V8_TARGET_ARCH_MIPS64)
383void WasmI32AtomicWaitDescriptor::InitializePlatformSpecific(
384 CallInterfaceDescriptorData* data) {
385 DefaultInitializePlatformSpecific(data, kParameterCount);
386}
387
388void WasmI64AtomicWaitDescriptor::InitializePlatformSpecific(
389 CallInterfaceDescriptorData* data) {
390 DefaultInitializePlatformSpecific(data, kParameterCount);
391}
392#endif
393
394void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
395 CallInterfaceDescriptorData* data) {
396 DefaultInitializePlatformSpecific(data, kParameterCount);
397}
398
399// static
400Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
401 return CallDescriptors::call_descriptor_data(CallDescriptors::RunMicrotasks)
402 ->register_param(0);
403}
404
405void RunMicrotasksDescriptor::InitializePlatformSpecific(
406 CallInterfaceDescriptorData* data) {
407 DefaultInitializePlatformSpecific(data, kParameterCount);
408}
409
410void I64ToBigIntDescriptor::InitializePlatformSpecific(
411 CallInterfaceDescriptorData* data) {
412 DefaultInitializePlatformSpecific(data, kParameterCount);
413}
414
415void BigIntToI64Descriptor::InitializePlatformSpecific(
416 CallInterfaceDescriptorData* data) {
417 DefaultInitializePlatformSpecific(data, kParameterCount);
418}
419
420} // namespace internal
421} // namespace v8
422