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