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/codegen/interface-descriptors.h"
6
7 #include "src/codegen/macro-assembler.h"
8
9 namespace v8 {
10 namespace internal {
11
InitializePlatformSpecific(int register_parameter_count,const Register * registers)12 void 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
InitializePlatformIndependent(Flags flags,int return_count,int parameter_count,const MachineType * machine_types,int machine_types_length)31 void 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
AllStackParametersAreTagged() const55 bool 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
Reset()66 void CallInterfaceDescriptorData::Reset() {
67 delete[] machine_types_;
68 machine_types_ = nullptr;
69 delete[] register_params_;
70 register_params_ = nullptr;
71 }
72
73 // static
74 CallInterfaceDescriptorData
75 CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
76
InitializeOncePerProcess()77 void 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
TearDown()90 void CallDescriptors::TearDown() {
91 for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
92 data.Reset();
93 }
94 }
95
JSDefaultInitializePlatformSpecific(CallInterfaceDescriptorData * data,int non_js_register_parameter_count)96 void 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
DebugName() const117 const 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)
IsValidFloatParameterRegister(Register reg)132 bool CallInterfaceDescriptor::IsValidFloatParameterRegister(Register reg) {
133 return true;
134 }
135 #endif
136
InitializePlatformSpecific(CallInterfaceDescriptorData * data)137 void VoidDescriptor::InitializePlatformSpecific(
138 CallInterfaceDescriptorData* data) {
139 data->InitializePlatformSpecific(0, nullptr);
140 }
141
InitializePlatformSpecific(CallInterfaceDescriptorData * data)142 void AllocateDescriptor::InitializePlatformSpecific(
143 CallInterfaceDescriptorData* data) {
144 Register registers[] = {kAllocateSizeRegister};
145 data->InitializePlatformSpecific(arraysize(registers), registers);
146 }
147
InitializePlatformSpecific(CallInterfaceDescriptorData * data)148 void CEntry1ArgvOnStackDescriptor::InitializePlatformSpecific(
149 CallInterfaceDescriptorData* data) {
150 Register registers[] = {kRuntimeCallArgCountRegister,
151 kRuntimeCallFunctionRegister};
152 data->InitializePlatformSpecific(arraysize(registers), registers);
153 }
154
155 namespace {
156
InterpreterCEntryDescriptor_InitializePlatformSpecific(CallInterfaceDescriptorData * data)157 void InterpreterCEntryDescriptor_InitializePlatformSpecific(
158 CallInterfaceDescriptorData* data) {
159 Register registers[] = {kRuntimeCallArgCountRegister,
160 kRuntimeCallArgvRegister,
161 kRuntimeCallFunctionRegister};
162 data->InitializePlatformSpecific(arraysize(registers), registers);
163 }
164
165 } // namespace
166
InitializePlatformSpecific(CallInterfaceDescriptorData * data)167 void InterpreterCEntry1Descriptor::InitializePlatformSpecific(
168 CallInterfaceDescriptorData* data) {
169 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
170 }
171
InitializePlatformSpecific(CallInterfaceDescriptorData * data)172 void InterpreterCEntry2Descriptor::InitializePlatformSpecific(
173 CallInterfaceDescriptorData* data) {
174 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
175 }
176
InitializePlatformSpecific(CallInterfaceDescriptorData * data)177 void FastNewFunctionContextDescriptor::InitializePlatformSpecific(
178 CallInterfaceDescriptorData* data) {
179 Register registers[] = {ScopeInfoRegister(), SlotsRegister()};
180 data->InitializePlatformSpecific(arraysize(registers), registers);
181 }
182
InitializePlatformSpecific(CallInterfaceDescriptorData * data)183 void FastNewObjectDescriptor::InitializePlatformSpecific(
184 CallInterfaceDescriptorData* data) {
185 Register registers[] = {TargetRegister(), NewTargetRegister()};
186 data->InitializePlatformSpecific(arraysize(registers), registers);
187 }
188
TargetRegister()189 const Register FastNewObjectDescriptor::TargetRegister() {
190 return kJSFunctionRegister;
191 }
192
NewTargetRegister()193 const Register FastNewObjectDescriptor::NewTargetRegister() {
194 return kJavaScriptCallNewTargetRegister;
195 }
196
InitializePlatformSpecific(CallInterfaceDescriptorData * data)197 void LoadDescriptor::InitializePlatformSpecific(
198 CallInterfaceDescriptorData* data) {
199 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
200 data->InitializePlatformSpecific(arraysize(registers), registers);
201 }
202
InitializePlatformSpecific(CallInterfaceDescriptorData * data)203 void LoadNoFeedbackDescriptor::InitializePlatformSpecific(
204 CallInterfaceDescriptorData* data) {
205 Register registers[] = {ReceiverRegister(), NameRegister(), ICKindRegister()};
206 data->InitializePlatformSpecific(arraysize(registers), registers);
207 }
208
InitializePlatformSpecific(CallInterfaceDescriptorData * data)209 void LoadGlobalDescriptor::InitializePlatformSpecific(
210 CallInterfaceDescriptorData* data) {
211 Register registers[] = {NameRegister(), SlotRegister()};
212 data->InitializePlatformSpecific(arraysize(registers), registers);
213 }
214
InitializePlatformSpecific(CallInterfaceDescriptorData * data)215 void LoadGlobalNoFeedbackDescriptor::InitializePlatformSpecific(
216 CallInterfaceDescriptorData* data) {
217 Register registers[] = {NameRegister(), ICKindRegister()};
218 data->InitializePlatformSpecific(arraysize(registers), registers);
219 }
220
InitializePlatformSpecific(CallInterfaceDescriptorData * data)221 void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
222 CallInterfaceDescriptorData* data) {
223 Register registers[] = {NameRegister(), SlotRegister(), VectorRegister()};
224 data->InitializePlatformSpecific(arraysize(registers), registers);
225 }
226
InitializePlatformSpecific(CallInterfaceDescriptorData * data)227 void StoreGlobalDescriptor::InitializePlatformSpecific(
228 CallInterfaceDescriptorData* data) {
229 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister()};
230
231 int len = arraysize(registers) - kStackArgumentsCount;
232 data->InitializePlatformSpecific(len, registers);
233 }
234
InitializePlatformSpecific(CallInterfaceDescriptorData * data)235 void StoreGlobalWithVectorDescriptor::InitializePlatformSpecific(
236 CallInterfaceDescriptorData* data) {
237 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister(),
238 VectorRegister()};
239 int len = arraysize(registers) - kStackArgumentsCount;
240 data->InitializePlatformSpecific(len, registers);
241 }
242
InitializePlatformSpecific(CallInterfaceDescriptorData * data)243 void StoreDescriptor::InitializePlatformSpecific(
244 CallInterfaceDescriptorData* data) {
245 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
246 SlotRegister()};
247
248 int len = arraysize(registers) - kStackArgumentsCount;
249 data->InitializePlatformSpecific(len, registers);
250 }
251
InitializePlatformSpecific(CallInterfaceDescriptorData * data)252 void StoreTransitionDescriptor::InitializePlatformSpecific(
253 CallInterfaceDescriptorData* data) {
254 Register registers[] = {
255 ReceiverRegister(), NameRegister(), MapRegister(),
256 ValueRegister(), SlotRegister(), VectorRegister(),
257 };
258 int len = arraysize(registers) - kStackArgumentsCount;
259 data->InitializePlatformSpecific(len, registers);
260 }
261
InitializePlatformSpecific(CallInterfaceDescriptorData * data)262 void StringAtDescriptor::InitializePlatformSpecific(
263 CallInterfaceDescriptorData* data) {
264 DefaultInitializePlatformSpecific(data, kParameterCount);
265 }
266
InitializePlatformSpecific(CallInterfaceDescriptorData * data)267 void StringAtAsStringDescriptor::InitializePlatformSpecific(
268 CallInterfaceDescriptorData* data) {
269 DefaultInitializePlatformSpecific(data, kParameterCount);
270 }
271
InitializePlatformSpecific(CallInterfaceDescriptorData * data)272 void StringSubstringDescriptor::InitializePlatformSpecific(
273 CallInterfaceDescriptorData* data) {
274 DefaultInitializePlatformSpecific(data, kParameterCount);
275 }
276
InitializePlatformSpecific(CallInterfaceDescriptorData * data)277 void TypeConversionDescriptor::InitializePlatformSpecific(
278 CallInterfaceDescriptorData* data) {
279 Register registers[] = {ArgumentRegister()};
280 data->InitializePlatformSpecific(arraysize(registers), registers);
281 }
282
InitializePlatformSpecific(CallInterfaceDescriptorData * data)283 void TypeConversionStackParameterDescriptor::InitializePlatformSpecific(
284 CallInterfaceDescriptorData* data) {
285 data->InitializePlatformSpecific(0, nullptr);
286 }
287
InitializePlatformSpecific(CallInterfaceDescriptorData * data)288 void AsyncFunctionStackParameterDescriptor::InitializePlatformSpecific(
289 CallInterfaceDescriptorData* data) {
290 data->InitializePlatformSpecific(0, nullptr);
291 }
292
InitializePlatformSpecific(CallInterfaceDescriptorData * data)293 void GetIteratorStackParameterDescriptor::InitializePlatformSpecific(
294 CallInterfaceDescriptorData* data) {
295 data->InitializePlatformSpecific(0, nullptr);
296 }
297
InitializePlatformSpecific(CallInterfaceDescriptorData * data)298 void LoadWithVectorDescriptor::InitializePlatformSpecific(
299 CallInterfaceDescriptorData* data) {
300 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
301 VectorRegister()};
302 // TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
303 // to allow no_reg entries.
304 // DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), SlotRegister(),
305 // VectorRegister(), kRootRegister));
306 int len = arraysize(registers) - kStackArgumentsCount;
307 data->InitializePlatformSpecific(len, registers);
308 }
309
InitializePlatformSpecific(CallInterfaceDescriptorData * data)310 void StoreWithVectorDescriptor::InitializePlatformSpecific(
311 CallInterfaceDescriptorData* data) {
312 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
313 SlotRegister(), VectorRegister()};
314 // TODO(jgruber): This DCHECK could be enabled if RegisterBase::ListOf were
315 // to allow no_reg entries.
316 // DCHECK(!AreAliased(ReceiverRegister(), NameRegister(), kRootRegister));
317 int len = arraysize(registers) - kStackArgumentsCount;
318 data->InitializePlatformSpecific(len, registers);
319 }
320
ReceiverRegister()321 const Register ApiGetterDescriptor::ReceiverRegister() {
322 return LoadDescriptor::ReceiverRegister();
323 }
324
InitializePlatformSpecific(CallInterfaceDescriptorData * data)325 void ApiGetterDescriptor::InitializePlatformSpecific(
326 CallInterfaceDescriptorData* data) {
327 Register registers[] = {ReceiverRegister(), HolderRegister(),
328 CallbackRegister()};
329 data->InitializePlatformSpecific(arraysize(registers), registers);
330 }
331
InitializePlatformSpecific(CallInterfaceDescriptorData * data)332 void ContextOnlyDescriptor::InitializePlatformSpecific(
333 CallInterfaceDescriptorData* data) {
334 data->InitializePlatformSpecific(0, nullptr);
335 }
336
InitializePlatformSpecific(CallInterfaceDescriptorData * data)337 void NoContextDescriptor::InitializePlatformSpecific(
338 CallInterfaceDescriptorData* data) {
339 data->InitializePlatformSpecific(0, nullptr);
340 }
341
InitializePlatformSpecific(CallInterfaceDescriptorData * data)342 void GrowArrayElementsDescriptor::InitializePlatformSpecific(
343 CallInterfaceDescriptorData* data) {
344 Register registers[] = {ObjectRegister(), KeyRegister()};
345 data->InitializePlatformSpecific(arraysize(registers), registers);
346 }
347
InitializePlatformSpecific(CallInterfaceDescriptorData * data)348 void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
349 CallInterfaceDescriptorData* data) {
350 DefaultInitializePlatformSpecific(data, kParameterCount);
351 }
352
InitializePlatformSpecific(CallInterfaceDescriptorData * data)353 void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
354 CallInterfaceDescriptorData* data) {
355 // This descriptor must use the same set of registers as the
356 // ArrayNArgumentsConstructorDescriptor.
357 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
358 }
359
InitializePlatformSpecific(CallInterfaceDescriptorData * data)360 void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
361 CallInterfaceDescriptorData* data) {
362 // This descriptor must use the same set of registers as the
363 // ArrayNArgumentsConstructorDescriptor.
364 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
365 }
366
InitializePlatformSpecific(CallInterfaceDescriptorData * data)367 void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
368 CallInterfaceDescriptorData* data) {
369 // Keep the arguments on the same registers as they were in
370 // ArrayConstructorDescriptor to avoid unnecessary register moves.
371 // kFunction, kAllocationSite, kActualArgumentsCount
372 Register registers[] = {kJavaScriptCallTargetRegister,
373 kJavaScriptCallExtraArg1Register,
374 kJavaScriptCallArgCountRegister};
375 data->InitializePlatformSpecific(arraysize(registers), registers);
376 }
377
InitializePlatformSpecific(CallInterfaceDescriptorData * data)378 void WasmMemoryGrowDescriptor::InitializePlatformSpecific(
379 CallInterfaceDescriptorData* data) {
380 DefaultInitializePlatformSpecific(data, kParameterCount);
381 }
382
InitializePlatformSpecific(CallInterfaceDescriptorData * data)383 void WasmTableInitDescriptor::InitializePlatformSpecific(
384 CallInterfaceDescriptorData* data) {
385 DefaultInitializePlatformSpecific(data,
386 kParameterCount - kStackArgumentsCount);
387 }
388
InitializePlatformSpecific(CallInterfaceDescriptorData * data)389 void WasmTableCopyDescriptor::InitializePlatformSpecific(
390 CallInterfaceDescriptorData* data) {
391 DefaultInitializePlatformSpecific(data,
392 kParameterCount - kStackArgumentsCount);
393 }
394
InitializePlatformSpecific(CallInterfaceDescriptorData * data)395 void WasmTableGetDescriptor::InitializePlatformSpecific(
396 CallInterfaceDescriptorData* data) {
397 DefaultInitializePlatformSpecific(data, kParameterCount);
398 }
399
InitializePlatformSpecific(CallInterfaceDescriptorData * data)400 void WasmTableSetDescriptor::InitializePlatformSpecific(
401 CallInterfaceDescriptorData* data) {
402 DefaultInitializePlatformSpecific(data, kParameterCount);
403 }
404
InitializePlatformSpecific(CallInterfaceDescriptorData * data)405 void WasmThrowDescriptor::InitializePlatformSpecific(
406 CallInterfaceDescriptorData* data) {
407 DefaultInitializePlatformSpecific(data, kParameterCount);
408 }
409
InitializePlatformSpecific(CallInterfaceDescriptorData * data)410 void WasmAtomicNotifyDescriptor::InitializePlatformSpecific(
411 CallInterfaceDescriptorData* data) {
412 DefaultInitializePlatformSpecific(data, kParameterCount);
413 }
414
415 #if !defined(V8_TARGET_ARCH_MIPS) && !defined(V8_TARGET_ARCH_MIPS64)
InitializePlatformSpecific(CallInterfaceDescriptorData * data)416 void WasmI32AtomicWait32Descriptor::InitializePlatformSpecific(
417 CallInterfaceDescriptorData* data) {
418 DefaultInitializePlatformSpecific(data, kParameterCount);
419 }
420
InitializePlatformSpecific(CallInterfaceDescriptorData * data)421 void WasmI32AtomicWait64Descriptor::InitializePlatformSpecific(
422 CallInterfaceDescriptorData* data) {
423 DefaultInitializePlatformSpecific(data, kParameterCount);
424 }
425
InitializePlatformSpecific(CallInterfaceDescriptorData * data)426 void WasmI64AtomicWait32Descriptor::InitializePlatformSpecific(
427 CallInterfaceDescriptorData* data) {
428 DefaultInitializePlatformSpecific(data,
429 kParameterCount - kStackArgumentsCount);
430 }
431
InitializePlatformSpecific(CallInterfaceDescriptorData * data)432 void WasmI64AtomicWait64Descriptor::InitializePlatformSpecific(
433 CallInterfaceDescriptorData* data) {
434 DefaultInitializePlatformSpecific(data, kParameterCount);
435 }
436 #endif
437
InitializePlatformSpecific(CallInterfaceDescriptorData * data)438 void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
439 CallInterfaceDescriptorData* data) {
440 DefaultInitializePlatformSpecific(data, kParameterCount);
441 }
442
443 // static
MicrotaskQueueRegister()444 Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
445 return CallDescriptors::call_descriptor_data(CallDescriptors::RunMicrotasks)
446 ->register_param(0);
447 }
448
InitializePlatformSpecific(CallInterfaceDescriptorData * data)449 void RunMicrotasksDescriptor::InitializePlatformSpecific(
450 CallInterfaceDescriptorData* data) {
451 DefaultInitializePlatformSpecific(data, kParameterCount);
452 }
453
InitializePlatformSpecific(CallInterfaceDescriptorData * data)454 void I64ToBigIntDescriptor::InitializePlatformSpecific(
455 CallInterfaceDescriptorData* data) {
456 DefaultInitializePlatformSpecific(data, kParameterCount);
457 }
458
InitializePlatformSpecific(CallInterfaceDescriptorData * data)459 void I32PairToBigIntDescriptor::InitializePlatformSpecific(
460 CallInterfaceDescriptorData* data) {
461 DefaultInitializePlatformSpecific(data, kParameterCount);
462 }
463
InitializePlatformSpecific(CallInterfaceDescriptorData * data)464 void BigIntToI64Descriptor::InitializePlatformSpecific(
465 CallInterfaceDescriptorData* data) {
466 DefaultInitializePlatformSpecific(data, kParameterCount);
467 }
468
InitializePlatformSpecific(CallInterfaceDescriptorData * data)469 void BigIntToI32PairDescriptor::InitializePlatformSpecific(
470 CallInterfaceDescriptorData* data) {
471 DefaultInitializePlatformSpecific(data, kParameterCount);
472 }
473
474 } // namespace internal
475 } // namespace v8
476