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 namespace v8 {
8 namespace internal {
9
InitializePlatformSpecific(int register_parameter_count,const Register * registers)10 void CallInterfaceDescriptorData::InitializePlatformSpecific(
11 int register_parameter_count, const Register* registers) {
12 DCHECK(!IsInitializedPlatformIndependent());
13
14 register_param_count_ = register_parameter_count;
15
16 // InterfaceDescriptor owns a copy of the registers array.
17 register_params_ = NewArray<Register>(register_parameter_count, no_reg);
18 for (int i = 0; i < register_parameter_count; i++) {
19 register_params_[i] = registers[i];
20 }
21 }
22
InitializePlatformIndependent(Flags flags,int return_count,int parameter_count,const MachineType * machine_types,int machine_types_length)23 void CallInterfaceDescriptorData::InitializePlatformIndependent(
24 Flags flags, int return_count, int parameter_count,
25 const MachineType* machine_types, int machine_types_length) {
26 DCHECK(IsInitializedPlatformSpecific());
27
28 flags_ = flags;
29 return_count_ = return_count;
30 param_count_ = parameter_count;
31 const int types_length = return_count_ + param_count_;
32
33 // Machine types are either fully initialized or null.
34 if (machine_types == nullptr) {
35 machine_types_ =
36 NewArray<MachineType>(types_length, MachineType::AnyTagged());
37 } else {
38 DCHECK_EQ(machine_types_length, types_length);
39 machine_types_ = NewArray<MachineType>(types_length);
40 for (int i = 0; i < types_length; i++) machine_types_[i] = machine_types[i];
41 }
42
43 DCHECK(AllStackParametersAreTagged());
44 }
45
46 #ifdef DEBUG
AllStackParametersAreTagged() const47 bool CallInterfaceDescriptorData::AllStackParametersAreTagged() const {
48 DCHECK(IsInitialized());
49 const int types_length = return_count_ + param_count_;
50 const int first_stack_param = return_count_ + register_param_count_;
51 for (int i = first_stack_param; i < types_length; i++) {
52 if (!machine_types_[i].IsTagged()) return false;
53 }
54 return true;
55 }
56 #endif // DEBUG
57
Reset()58 void CallInterfaceDescriptorData::Reset() {
59 delete[] machine_types_;
60 machine_types_ = nullptr;
61 delete[] register_params_;
62 register_params_ = nullptr;
63 }
64
65 // static
66 CallInterfaceDescriptorData
67 CallDescriptors::call_descriptor_data_[NUMBER_OF_DESCRIPTORS];
68
InitializeOncePerProcess()69 void CallDescriptors::InitializeOncePerProcess() {
70 #define INTERFACE_DESCRIPTOR(name, ...) \
71 name##Descriptor().Initialize(&call_descriptor_data_[CallDescriptors::name]);
72 INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR)
73 #undef INTERFACE_DESCRIPTOR
74
75 DCHECK(ContextOnlyDescriptor{}.HasContextParameter());
76 DCHECK(!NoContextDescriptor{}.HasContextParameter());
77 DCHECK(!AllocateDescriptor{}.HasContextParameter());
78 DCHECK(!AllocateHeapNumberDescriptor{}.HasContextParameter());
79 DCHECK(!AbortDescriptor{}.HasContextParameter());
80 }
81
TearDown()82 void CallDescriptors::TearDown() {
83 for (CallInterfaceDescriptorData& data : call_descriptor_data_) {
84 data.Reset();
85 }
86 }
87
JSDefaultInitializePlatformSpecific(CallInterfaceDescriptorData * data,int non_js_register_parameter_count)88 void CallInterfaceDescriptor::JSDefaultInitializePlatformSpecific(
89 CallInterfaceDescriptorData* data, int non_js_register_parameter_count) {
90 DCHECK_LE(static_cast<unsigned>(non_js_register_parameter_count), 1);
91
92 // 3 is for kTarget, kNewTarget and kActualArgumentsCount
93 int register_parameter_count = 3 + non_js_register_parameter_count;
94
95 DCHECK(!AreAliased(
96 kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
97 kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register));
98
99 const Register default_js_stub_registers[] = {
100 kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
101 kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register};
102
103 CHECK_LE(static_cast<size_t>(register_parameter_count),
104 arraysize(default_js_stub_registers));
105 data->InitializePlatformSpecific(register_parameter_count,
106 default_js_stub_registers);
107 }
108
DebugName() const109 const char* CallInterfaceDescriptor::DebugName() const {
110 CallDescriptors::Key key = CallDescriptors::GetKey(data_);
111 switch (key) {
112 #define DEF_CASE(name, ...) \
113 case CallDescriptors::name: \
114 return #name " Descriptor";
115 INTERFACE_DESCRIPTOR_LIST(DEF_CASE)
116 #undef DEF_CASE
117 case CallDescriptors::NUMBER_OF_DESCRIPTORS:
118 break;
119 }
120 return "";
121 }
122
123
InitializePlatformSpecific(CallInterfaceDescriptorData * data)124 void VoidDescriptor::InitializePlatformSpecific(
125 CallInterfaceDescriptorData* data) {
126 data->InitializePlatformSpecific(0, nullptr);
127 }
128
InitializePlatformSpecific(CallInterfaceDescriptorData * data)129 void AllocateDescriptor::InitializePlatformSpecific(
130 CallInterfaceDescriptorData* data) {
131 Register registers[] = {kAllocateSizeRegister};
132 data->InitializePlatformSpecific(arraysize(registers), registers);
133 }
134
InitializePlatformSpecific(CallInterfaceDescriptorData * data)135 void CEntry1ArgvOnStackDescriptor::InitializePlatformSpecific(
136 CallInterfaceDescriptorData* data) {
137 Register registers[] = {kRuntimeCallArgCountRegister,
138 kRuntimeCallFunctionRegister};
139 data->InitializePlatformSpecific(arraysize(registers), registers);
140 }
141
142 namespace {
143
InterpreterCEntryDescriptor_InitializePlatformSpecific(CallInterfaceDescriptorData * data)144 void InterpreterCEntryDescriptor_InitializePlatformSpecific(
145 CallInterfaceDescriptorData* data) {
146 Register registers[] = {kRuntimeCallArgCountRegister,
147 kRuntimeCallArgvRegister,
148 kRuntimeCallFunctionRegister};
149 data->InitializePlatformSpecific(arraysize(registers), registers);
150 }
151
152 } // namespace
153
InitializePlatformSpecific(CallInterfaceDescriptorData * data)154 void InterpreterCEntry1Descriptor::InitializePlatformSpecific(
155 CallInterfaceDescriptorData* data) {
156 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
157 }
158
InitializePlatformSpecific(CallInterfaceDescriptorData * data)159 void InterpreterCEntry2Descriptor::InitializePlatformSpecific(
160 CallInterfaceDescriptorData* data) {
161 InterpreterCEntryDescriptor_InitializePlatformSpecific(data);
162 }
163
InitializePlatformSpecific(CallInterfaceDescriptorData * data)164 void FastNewFunctionContextDescriptor::InitializePlatformSpecific(
165 CallInterfaceDescriptorData* data) {
166 Register registers[] = {ScopeInfoRegister(), SlotsRegister()};
167 data->InitializePlatformSpecific(arraysize(registers), registers);
168 }
169
InitializePlatformSpecific(CallInterfaceDescriptorData * data)170 void FastNewObjectDescriptor::InitializePlatformSpecific(
171 CallInterfaceDescriptorData* data) {
172 Register registers[] = {TargetRegister(), NewTargetRegister()};
173 data->InitializePlatformSpecific(arraysize(registers), registers);
174 }
175
TargetRegister()176 const Register FastNewObjectDescriptor::TargetRegister() {
177 return kJSFunctionRegister;
178 }
179
NewTargetRegister()180 const Register FastNewObjectDescriptor::NewTargetRegister() {
181 return kJavaScriptCallNewTargetRegister;
182 }
183
184
InitializePlatformSpecific(CallInterfaceDescriptorData * data)185 void LoadDescriptor::InitializePlatformSpecific(
186 CallInterfaceDescriptorData* data) {
187 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister()};
188 data->InitializePlatformSpecific(arraysize(registers), registers);
189 }
190
InitializePlatformSpecific(CallInterfaceDescriptorData * data)191 void LoadGlobalDescriptor::InitializePlatformSpecific(
192 CallInterfaceDescriptorData* data) {
193 Register registers[] = {NameRegister(), SlotRegister()};
194 data->InitializePlatformSpecific(arraysize(registers), registers);
195 }
196
InitializePlatformSpecific(CallInterfaceDescriptorData * data)197 void LoadGlobalWithVectorDescriptor::InitializePlatformSpecific(
198 CallInterfaceDescriptorData* data) {
199 Register registers[] = {NameRegister(), SlotRegister(), VectorRegister()};
200 data->InitializePlatformSpecific(arraysize(registers), registers);
201 }
202
InitializePlatformSpecific(CallInterfaceDescriptorData * data)203 void StoreGlobalDescriptor::InitializePlatformSpecific(
204 CallInterfaceDescriptorData* data) {
205 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister()};
206
207 int len = arraysize(registers) - kStackArgumentsCount;
208 data->InitializePlatformSpecific(len, registers);
209 }
210
InitializePlatformSpecific(CallInterfaceDescriptorData * data)211 void StoreGlobalWithVectorDescriptor::InitializePlatformSpecific(
212 CallInterfaceDescriptorData* data) {
213 Register registers[] = {NameRegister(), ValueRegister(), SlotRegister(),
214 VectorRegister()};
215 int len = arraysize(registers) - kStackArgumentsCount;
216 data->InitializePlatformSpecific(len, registers);
217 }
218
InitializePlatformSpecific(CallInterfaceDescriptorData * data)219 void StoreDescriptor::InitializePlatformSpecific(
220 CallInterfaceDescriptorData* data) {
221 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
222 SlotRegister()};
223
224 int len = arraysize(registers) - kStackArgumentsCount;
225 data->InitializePlatformSpecific(len, registers);
226 }
227
InitializePlatformSpecific(CallInterfaceDescriptorData * data)228 void StoreTransitionDescriptor::InitializePlatformSpecific(
229 CallInterfaceDescriptorData* data) {
230 Register registers[] = {
231 ReceiverRegister(), NameRegister(), MapRegister(),
232 ValueRegister(), SlotRegister(), VectorRegister(),
233 };
234 int len = arraysize(registers) - kStackArgumentsCount;
235 data->InitializePlatformSpecific(len, registers);
236 }
237
InitializePlatformSpecific(CallInterfaceDescriptorData * data)238 void StringAtDescriptor::InitializePlatformSpecific(
239 CallInterfaceDescriptorData* data) {
240 DefaultInitializePlatformSpecific(data, kParameterCount);
241 }
242
InitializePlatformSpecific(CallInterfaceDescriptorData * data)243 void StringSubstringDescriptor::InitializePlatformSpecific(
244 CallInterfaceDescriptorData* data) {
245 DefaultInitializePlatformSpecific(data, kParameterCount);
246 }
247
InitializePlatformSpecific(CallInterfaceDescriptorData * data)248 void TypeConversionDescriptor::InitializePlatformSpecific(
249 CallInterfaceDescriptorData* data) {
250 Register registers[] = {ArgumentRegister()};
251 data->InitializePlatformSpecific(arraysize(registers), registers);
252 }
253
InitializePlatformSpecific(CallInterfaceDescriptorData * data)254 void TypeConversionStackParameterDescriptor::InitializePlatformSpecific(
255 CallInterfaceDescriptorData* data) {
256 data->InitializePlatformSpecific(0, nullptr);
257 }
258
InitializePlatformSpecific(CallInterfaceDescriptorData * data)259 void LoadWithVectorDescriptor::InitializePlatformSpecific(
260 CallInterfaceDescriptorData* data) {
261 Register registers[] = {ReceiverRegister(), NameRegister(), SlotRegister(),
262 VectorRegister()};
263 data->InitializePlatformSpecific(arraysize(registers), registers);
264 }
265
InitializePlatformSpecific(CallInterfaceDescriptorData * data)266 void StoreWithVectorDescriptor::InitializePlatformSpecific(
267 CallInterfaceDescriptorData* data) {
268 Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
269 SlotRegister(), VectorRegister()};
270 int len = arraysize(registers) - kStackArgumentsCount;
271 data->InitializePlatformSpecific(len, registers);
272 }
273
ReceiverRegister()274 const Register ApiGetterDescriptor::ReceiverRegister() {
275 return LoadDescriptor::ReceiverRegister();
276 }
277
InitializePlatformSpecific(CallInterfaceDescriptorData * data)278 void ApiGetterDescriptor::InitializePlatformSpecific(
279 CallInterfaceDescriptorData* data) {
280 Register registers[] = {ReceiverRegister(), HolderRegister(),
281 CallbackRegister()};
282 data->InitializePlatformSpecific(arraysize(registers), registers);
283 }
284
InitializePlatformSpecific(CallInterfaceDescriptorData * data)285 void ContextOnlyDescriptor::InitializePlatformSpecific(
286 CallInterfaceDescriptorData* data) {
287 data->InitializePlatformSpecific(0, nullptr);
288 }
289
InitializePlatformSpecific(CallInterfaceDescriptorData * data)290 void NoContextDescriptor::InitializePlatformSpecific(
291 CallInterfaceDescriptorData* data) {
292 data->InitializePlatformSpecific(0, nullptr);
293 }
294
InitializePlatformSpecific(CallInterfaceDescriptorData * data)295 void GrowArrayElementsDescriptor::InitializePlatformSpecific(
296 CallInterfaceDescriptorData* data) {
297 Register registers[] = {ObjectRegister(), KeyRegister()};
298 data->InitializePlatformSpecific(arraysize(registers), registers);
299 }
300
InitializePlatformSpecific(CallInterfaceDescriptorData * data)301 void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
302 CallInterfaceDescriptorData* data) {
303 DefaultInitializePlatformSpecific(data, 3);
304 }
305
InitializePlatformSpecific(CallInterfaceDescriptorData * data)306 void ArrayNoArgumentConstructorDescriptor::InitializePlatformSpecific(
307 CallInterfaceDescriptorData* data) {
308 // This descriptor must use the same set of registers as the
309 // ArrayNArgumentsConstructorDescriptor.
310 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
311 }
312
InitializePlatformSpecific(CallInterfaceDescriptorData * data)313 void ArraySingleArgumentConstructorDescriptor::InitializePlatformSpecific(
314 CallInterfaceDescriptorData* data) {
315 // This descriptor must use the same set of registers as the
316 // ArrayNArgumentsConstructorDescriptor.
317 ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(data);
318 }
319
InitializePlatformSpecific(CallInterfaceDescriptorData * data)320 void ArrayNArgumentsConstructorDescriptor::InitializePlatformSpecific(
321 CallInterfaceDescriptorData* data) {
322 // Keep the arguments on the same registers as they were in
323 // ArrayConstructorDescriptor to avoid unnecessary register moves.
324 // kFunction, kAllocationSite, kActualArgumentsCount
325 Register registers[] = {kJavaScriptCallTargetRegister,
326 kJavaScriptCallExtraArg1Register,
327 kJavaScriptCallArgCountRegister};
328 data->InitializePlatformSpecific(arraysize(registers), registers);
329 }
330
InitializePlatformSpecific(CallInterfaceDescriptorData * data)331 void WasmGrowMemoryDescriptor::InitializePlatformSpecific(
332 CallInterfaceDescriptorData* data) {
333 DefaultInitializePlatformSpecific(data, kParameterCount);
334 }
335
InitializePlatformSpecific(CallInterfaceDescriptorData * data)336 void CloneObjectWithVectorDescriptor::InitializePlatformSpecific(
337 CallInterfaceDescriptorData* data) {
338 DefaultInitializePlatformSpecific(data, kParameterCount);
339 }
340
341 } // namespace internal
342 } // namespace v8
343