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 #if V8_TARGET_ARCH_IA32
6
7 #include "src/codegen/interface-descriptors.h"
8
9 #include "src/execution/frames.h"
10
11 namespace v8 {
12 namespace internal {
13
ContextRegister()14 const Register CallInterfaceDescriptor::ContextRegister() { return esi; }
15
DefaultInitializePlatformSpecific(CallInterfaceDescriptorData * data,int register_parameter_count)16 void CallInterfaceDescriptor::DefaultInitializePlatformSpecific(
17 CallInterfaceDescriptorData* data, int register_parameter_count) {
18 constexpr Register default_stub_registers[] = {eax, ecx, edx, edi};
19 STATIC_ASSERT(arraysize(default_stub_registers) == kMaxBuiltinRegisterParams);
20 CHECK_LE(static_cast<size_t>(register_parameter_count),
21 arraysize(default_stub_registers));
22 data->InitializePlatformSpecific(register_parameter_count,
23 default_stub_registers);
24 }
25
InitializePlatformSpecific(CallInterfaceDescriptorData * data)26 void RecordWriteDescriptor::InitializePlatformSpecific(
27 CallInterfaceDescriptorData* data) {
28 static const Register default_stub_registers[] = {ecx, edx, esi, edi,
29 kReturnRegister0};
30
31 data->RestrictAllocatableRegisters(default_stub_registers,
32 arraysize(default_stub_registers));
33
34 CHECK_LE(static_cast<size_t>(kParameterCount),
35 arraysize(default_stub_registers));
36 data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
37 }
38
InitializePlatformSpecific(CallInterfaceDescriptorData * data)39 void EphemeronKeyBarrierDescriptor::InitializePlatformSpecific(
40 CallInterfaceDescriptorData* data) {
41 static const Register default_stub_registers[] = {ecx, edx, esi, edi,
42 kReturnRegister0};
43
44 data->RestrictAllocatableRegisters(default_stub_registers,
45 arraysize(default_stub_registers));
46
47 CHECK_LE(static_cast<size_t>(kParameterCount),
48 arraysize(default_stub_registers));
49 data->InitializePlatformSpecific(kParameterCount, default_stub_registers);
50 }
51
ReceiverRegister()52 const Register LoadDescriptor::ReceiverRegister() { return edx; }
NameRegister()53 const Register LoadDescriptor::NameRegister() { return ecx; }
SlotRegister()54 const Register LoadDescriptor::SlotRegister() { return eax; }
55
VectorRegister()56 const Register LoadWithVectorDescriptor::VectorRegister() { return no_reg; }
57
58 const Register
LookupStartObjectRegister()59 LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister() {
60 return edi;
61 }
62
ReceiverRegister()63 const Register StoreDescriptor::ReceiverRegister() { return edx; }
NameRegister()64 const Register StoreDescriptor::NameRegister() { return ecx; }
ValueRegister()65 const Register StoreDescriptor::ValueRegister() { return no_reg; }
SlotRegister()66 const Register StoreDescriptor::SlotRegister() { return no_reg; }
67
VectorRegister()68 const Register StoreWithVectorDescriptor::VectorRegister() { return no_reg; }
69
SlotRegister()70 const Register StoreTransitionDescriptor::SlotRegister() { return no_reg; }
VectorRegister()71 const Register StoreTransitionDescriptor::VectorRegister() { return no_reg; }
MapRegister()72 const Register StoreTransitionDescriptor::MapRegister() { return edi; }
73
HolderRegister()74 const Register ApiGetterDescriptor::HolderRegister() { return ecx; }
CallbackRegister()75 const Register ApiGetterDescriptor::CallbackRegister() { return eax; }
76
ObjectRegister()77 const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
KeyRegister()78 const Register GrowArrayElementsDescriptor::KeyRegister() { return ecx; }
79
80 // static
ArgumentRegister()81 const Register TypeConversionDescriptor::ArgumentRegister() { return eax; }
82
InitializePlatformSpecific(CallInterfaceDescriptorData * data)83 void TypeofDescriptor::InitializePlatformSpecific(
84 CallInterfaceDescriptorData* data) {
85 Register registers[] = {ecx};
86 data->InitializePlatformSpecific(arraysize(registers), registers);
87 }
88
InitializePlatformSpecific(CallInterfaceDescriptorData * data)89 void CallTrampolineDescriptor::InitializePlatformSpecific(
90 CallInterfaceDescriptorData* data) {
91 // eax : number of arguments
92 // edi : the target to call
93 Register registers[] = {edi, eax};
94 data->InitializePlatformSpecific(arraysize(registers), registers);
95 }
96
InitializePlatformSpecific(CallInterfaceDescriptorData * data)97 void CallVarargsDescriptor::InitializePlatformSpecific(
98 CallInterfaceDescriptorData* data) {
99 // eax : number of arguments (on the stack, not including receiver)
100 // edi : the target to call
101 // ecx : arguments list length (untagged)
102 // On the stack : arguments list (FixedArray)
103 Register registers[] = {edi, eax, ecx};
104 data->InitializePlatformSpecific(arraysize(registers), registers);
105 }
106
InitializePlatformSpecific(CallInterfaceDescriptorData * data)107 void CallForwardVarargsDescriptor::InitializePlatformSpecific(
108 CallInterfaceDescriptorData* data) {
109 // eax : number of arguments
110 // ecx : start index (to support rest parameters)
111 // edi : the target to call
112 Register registers[] = {edi, eax, ecx};
113 data->InitializePlatformSpecific(arraysize(registers), registers);
114 }
115
InitializePlatformSpecific(CallInterfaceDescriptorData * data)116 void CallFunctionTemplateDescriptor::InitializePlatformSpecific(
117 CallInterfaceDescriptorData* data) {
118 // edx : function template info
119 // ecx : number of arguments (on the stack, not including receiver)
120 Register registers[] = {edx, ecx};
121 data->InitializePlatformSpecific(arraysize(registers), registers);
122 }
123
InitializePlatformSpecific(CallInterfaceDescriptorData * data)124 void CallWithSpreadDescriptor::InitializePlatformSpecific(
125 CallInterfaceDescriptorData* data) {
126 // eax : number of arguments (on the stack, not including receiver)
127 // edi : the target to call
128 // ecx : the object to spread
129 Register registers[] = {edi, eax, ecx};
130 data->InitializePlatformSpecific(arraysize(registers), registers);
131 }
132
InitializePlatformSpecific(CallInterfaceDescriptorData * data)133 void CallWithArrayLikeDescriptor::InitializePlatformSpecific(
134 CallInterfaceDescriptorData* data) {
135 // edi : the target to call
136 // edx : the arguments list
137 Register registers[] = {edi, edx};
138 data->InitializePlatformSpecific(arraysize(registers), registers);
139 }
140
InitializePlatformSpecific(CallInterfaceDescriptorData * data)141 void ConstructVarargsDescriptor::InitializePlatformSpecific(
142 CallInterfaceDescriptorData* data) {
143 // eax : number of arguments (on the stack, not including receiver)
144 // edi : the target to call
145 // edx : the new target
146 // ecx : arguments list length (untagged)
147 // On the stack : arguments list (FixedArray)
148 Register registers[] = {edi, edx, eax, ecx};
149 data->InitializePlatformSpecific(arraysize(registers), registers);
150 }
151
InitializePlatformSpecific(CallInterfaceDescriptorData * data)152 void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
153 CallInterfaceDescriptorData* data) {
154 // eax : number of arguments
155 // edx : the new target
156 // ecx : start index (to support rest parameters)
157 // edi : the target to call
158 Register registers[] = {edi, edx, eax, ecx};
159 data->InitializePlatformSpecific(arraysize(registers), registers);
160 }
161
InitializePlatformSpecific(CallInterfaceDescriptorData * data)162 void ConstructWithSpreadDescriptor::InitializePlatformSpecific(
163 CallInterfaceDescriptorData* data) {
164 // eax : number of arguments (on the stack, not including receiver)
165 // edi : the target to call
166 // edx : the new target
167 // ecx : the object to spread
168 Register registers[] = {edi, edx, eax, ecx};
169 data->InitializePlatformSpecific(arraysize(registers), registers);
170 }
171
InitializePlatformSpecific(CallInterfaceDescriptorData * data)172 void ConstructWithArrayLikeDescriptor::InitializePlatformSpecific(
173 CallInterfaceDescriptorData* data) {
174 // edi : the target to call
175 // edx : the new target
176 // ecx : the arguments list
177 Register registers[] = {edi, edx, ecx};
178 data->InitializePlatformSpecific(arraysize(registers), registers);
179 }
180
InitializePlatformSpecific(CallInterfaceDescriptorData * data)181 void ConstructStubDescriptor::InitializePlatformSpecific(
182 CallInterfaceDescriptorData* data) {
183 // eax : number of arguments
184 // edx : the new target
185 // edi : the target to call
186 // ecx : allocation site or undefined
187 // TODO(jgruber): Remove the unused allocation site parameter.
188 Register registers[] = {edi, edx, eax, ecx};
189 data->InitializePlatformSpecific(arraysize(registers), registers);
190 }
191
InitializePlatformSpecific(CallInterfaceDescriptorData * data)192 void AbortDescriptor::InitializePlatformSpecific(
193 CallInterfaceDescriptorData* data) {
194 Register registers[] = {edx};
195 data->InitializePlatformSpecific(arraysize(registers), registers);
196 }
197
InitializePlatformSpecific(CallInterfaceDescriptorData * data)198 void CompareDescriptor::InitializePlatformSpecific(
199 CallInterfaceDescriptorData* data) {
200 Register registers[] = {edx, eax};
201 data->InitializePlatformSpecific(arraysize(registers), registers);
202 }
203
InitializePlatformSpecific(CallInterfaceDescriptorData * data)204 void BinaryOpDescriptor::InitializePlatformSpecific(
205 CallInterfaceDescriptorData* data) {
206 Register registers[] = {edx, eax};
207 data->InitializePlatformSpecific(arraysize(registers), registers);
208 }
209
InitializePlatformSpecific(CallInterfaceDescriptorData * data)210 void ArgumentsAdaptorDescriptor::InitializePlatformSpecific(
211 CallInterfaceDescriptorData* data) {
212 Register registers[] = {
213 edi, // JSFunction
214 edx, // the new target
215 eax, // actual number of arguments
216 ecx, // expected number of arguments
217 };
218 data->InitializePlatformSpecific(arraysize(registers), registers);
219 }
220
InitializePlatformSpecific(CallInterfaceDescriptorData * data)221 void ApiCallbackDescriptor::InitializePlatformSpecific(
222 CallInterfaceDescriptorData* data) {
223 Register registers[] = {
224 edx, // kApiFunctionAddress
225 ecx, // kArgc
226 eax, // kCallData
227 edi, // kHolder
228 };
229 data->InitializePlatformSpecific(arraysize(registers), registers);
230 }
231
InitializePlatformSpecific(CallInterfaceDescriptorData * data)232 void InterpreterDispatchDescriptor::InitializePlatformSpecific(
233 CallInterfaceDescriptorData* data) {
234 Register registers[] = {
235 kInterpreterAccumulatorRegister, kInterpreterBytecodeOffsetRegister,
236 kInterpreterBytecodeArrayRegister, kInterpreterDispatchTableRegister};
237 data->InitializePlatformSpecific(arraysize(registers), registers);
238 }
239
InitializePlatformSpecific(CallInterfaceDescriptorData * data)240 void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
241 CallInterfaceDescriptorData* data) {
242 Register registers[] = {
243 eax, // argument count (not including receiver)
244 ecx, // address of first argument
245 edi // the target callable to be call
246 };
247 data->InitializePlatformSpecific(arraysize(registers), registers);
248 }
249
InitializePlatformSpecific(CallInterfaceDescriptorData * data)250 void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
251 CallInterfaceDescriptorData* data) {
252 Register registers[] = {
253 eax, // argument count (not including receiver)
254 ecx, // address of first argument
255 };
256 data->InitializePlatformSpecific(arraysize(registers), registers);
257 }
258
InitializePlatformSpecific(CallInterfaceDescriptorData * data)259 void ResumeGeneratorDescriptor::InitializePlatformSpecific(
260 CallInterfaceDescriptorData* data) {
261 Register registers[] = {
262 eax, // the value to pass to the generator
263 edx // the JSGeneratorObject to resume
264 };
265 data->InitializePlatformSpecific(arraysize(registers), registers);
266 }
267
InitializePlatformSpecific(CallInterfaceDescriptorData * data)268 void FrameDropperTrampolineDescriptor::InitializePlatformSpecific(
269 CallInterfaceDescriptorData* data) {
270 Register registers[] = {
271 eax, // loaded new FP
272 };
273 data->InitializePlatformSpecific(arraysize(registers), registers);
274 }
275
InitializePlatformSpecific(CallInterfaceDescriptorData * data)276 void RunMicrotasksEntryDescriptor::InitializePlatformSpecific(
277 CallInterfaceDescriptorData* data) {
278 data->InitializePlatformSpecific(0, nullptr);
279 }
280
InitializePlatformSpecific(CallInterfaceDescriptorData * data)281 void WasmFloat32ToNumberDescriptor::InitializePlatformSpecific(
282 CallInterfaceDescriptorData* data) {
283 // Work around using eax, whose register code is 0, and leads to the FP
284 // parameter being passed via xmm0, which is not allocatable on ia32.
285 Register registers[] = {ecx};
286 data->InitializePlatformSpecific(arraysize(registers), registers);
287 }
288
InitializePlatformSpecific(CallInterfaceDescriptorData * data)289 void WasmFloat64ToNumberDescriptor::InitializePlatformSpecific(
290 CallInterfaceDescriptorData* data) {
291 // Work around using eax, whose register code is 0, and leads to the FP
292 // parameter being passed via xmm0, which is not allocatable on ia32.
293 Register registers[] = {ecx};
294 data->InitializePlatformSpecific(arraysize(registers), registers);
295 }
296
297 } // namespace internal
298 } // namespace v8
299
300 #endif // V8_TARGET_ARCH_IA32
301