]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGSlowPathGenerator.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGSlowPathGenerator.h
1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef DFGSlowPathGenerator_h
27 #define DFGSlowPathGenerator_h
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGCommon.h"
32 #include "DFGSilentRegisterSavePlan.h"
33 #include "DFGSpeculativeJIT.h"
34 #include <wtf/FastMalloc.h>
35
36 namespace JSC { namespace DFG {
37
38 class SlowPathGenerator {
39 WTF_MAKE_FAST_ALLOCATED;
40 public:
41 SlowPathGenerator(SpeculativeJIT* jit)
42 : m_currentNode(jit->m_currentNode)
43 {
44 }
45 virtual ~SlowPathGenerator() { }
46 void generate(SpeculativeJIT* jit)
47 {
48 m_label = jit->m_jit.label();
49 jit->m_currentNode = m_currentNode;
50 generateInternal(jit);
51 if (!ASSERT_DISABLED)
52 jit->m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
53 }
54 MacroAssembler::Label label() const { return m_label; }
55 virtual MacroAssembler::Call call() const
56 {
57 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
58 return MacroAssembler::Call();
59 }
60 protected:
61 virtual void generateInternal(SpeculativeJIT*) = 0;
62 MacroAssembler::Label m_label;
63 Node* m_currentNode;
64 };
65
66 template<typename JumpType>
67 class JumpingSlowPathGenerator : public SlowPathGenerator {
68 public:
69 JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
70 : SlowPathGenerator(jit)
71 , m_from(from)
72 , m_to(jit->m_jit.label())
73 {
74 }
75
76 protected:
77 void linkFrom(SpeculativeJIT* jit)
78 {
79 m_from.link(&jit->m_jit);
80 }
81
82 void jumpTo(SpeculativeJIT* jit)
83 {
84 jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
85 }
86
87 JumpType m_from;
88 MacroAssembler::Label m_to;
89 };
90
91 template<typename JumpType, typename FunctionType, typename ResultType>
92 class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
93 public:
94 CallSlowPathGenerator(
95 JumpType from, SpeculativeJIT* jit, FunctionType function,
96 SpillRegistersMode spillMode, ResultType result)
97 : JumpingSlowPathGenerator<JumpType>(from, jit)
98 , m_function(function)
99 , m_spillMode(spillMode)
100 , m_result(result)
101 {
102 if (m_spillMode == NeedToSpill)
103 jit->silentSpillAllRegistersImpl(false, m_plans, extractResult(result));
104 }
105
106 virtual MacroAssembler::Call call() const override
107 {
108 return m_call;
109 }
110
111 protected:
112 void setUp(SpeculativeJIT* jit)
113 {
114 this->linkFrom(jit);
115 if (m_spillMode == NeedToSpill) {
116 for (unsigned i = 0; i < m_plans.size(); ++i)
117 jit->silentSpill(m_plans[i]);
118 }
119 }
120
121 void recordCall(MacroAssembler::Call call)
122 {
123 m_call = call;
124 }
125
126 void tearDown(SpeculativeJIT* jit)
127 {
128 if (m_spillMode == NeedToSpill) {
129 GPRReg canTrample = SpeculativeJIT::pickCanTrample(extractResult(m_result));
130 for (unsigned i = m_plans.size(); i--;)
131 jit->silentFill(m_plans[i], canTrample);
132 }
133 this->jumpTo(jit);
134 }
135
136 FunctionType m_function;
137 SpillRegistersMode m_spillMode;
138 ResultType m_result;
139 MacroAssembler::Call m_call;
140 Vector<SilentRegisterSavePlan, 2> m_plans;
141 };
142
143 template<typename JumpType, typename FunctionType, typename ResultType>
144 class CallResultAndNoArgumentsSlowPathGenerator
145 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
146 public:
147 CallResultAndNoArgumentsSlowPathGenerator(
148 JumpType from, SpeculativeJIT* jit, FunctionType function,
149 SpillRegistersMode spillMode, ResultType result)
150 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
151 from, jit, function, spillMode, result)
152 {
153 }
154
155 protected:
156 virtual void generateInternal(SpeculativeJIT* jit) override
157 {
158 this->setUp(jit);
159 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result)));
160 this->tearDown(jit);
161 }
162 };
163
164 template<
165 typename JumpType, typename FunctionType, typename ResultType,
166 typename ArgumentType1>
167 class CallResultAndOneArgumentSlowPathGenerator
168 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
169 public:
170 CallResultAndOneArgumentSlowPathGenerator(
171 JumpType from, SpeculativeJIT* jit, FunctionType function,
172 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1)
173 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
174 from, jit, function, spillMode, result)
175 , m_argument1(argument1)
176 {
177 }
178
179 protected:
180 virtual void generateInternal(SpeculativeJIT* jit) override
181 {
182 this->setUp(jit);
183 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), m_argument1));
184 this->tearDown(jit);
185 }
186
187 ArgumentType1 m_argument1;
188 };
189
190 template<
191 typename JumpType, typename FunctionType, typename ResultType,
192 typename ArgumentType1, typename ArgumentType2>
193 class CallResultAndTwoArgumentsSlowPathGenerator
194 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
195 public:
196 CallResultAndTwoArgumentsSlowPathGenerator(
197 JumpType from, SpeculativeJIT* jit, FunctionType function,
198 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
199 ArgumentType2 argument2)
200 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
201 from, jit, function, spillMode, result)
202 , m_argument1(argument1)
203 , m_argument2(argument2)
204 {
205 }
206
207 protected:
208 virtual void generateInternal(SpeculativeJIT* jit) override
209 {
210 this->setUp(jit);
211 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), m_argument1, m_argument2));
212 this->tearDown(jit);
213 }
214
215 ArgumentType1 m_argument1;
216 ArgumentType2 m_argument2;
217 };
218
219 template<
220 typename JumpType, typename FunctionType, typename ResultType,
221 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
222 class CallResultAndThreeArgumentsSlowPathGenerator
223 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
224 public:
225 CallResultAndThreeArgumentsSlowPathGenerator(
226 JumpType from, SpeculativeJIT* jit, FunctionType function,
227 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
228 ArgumentType2 argument2, ArgumentType3 argument3)
229 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
230 from, jit, function, spillMode, result)
231 , m_argument1(argument1)
232 , m_argument2(argument2)
233 , m_argument3(argument3)
234 {
235 }
236
237 protected:
238 virtual void generateInternal(SpeculativeJIT* jit) override
239 {
240 this->setUp(jit);
241 this->recordCall(
242 jit->callOperation(
243 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
244 m_argument3));
245 this->tearDown(jit);
246 }
247
248 ArgumentType1 m_argument1;
249 ArgumentType2 m_argument2;
250 ArgumentType3 m_argument3;
251 };
252
253 template<
254 typename JumpType, typename FunctionType, typename ResultType,
255 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
256 typename ArgumentType4>
257 class CallResultAndFourArgumentsSlowPathGenerator
258 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
259 public:
260 CallResultAndFourArgumentsSlowPathGenerator(
261 JumpType from, SpeculativeJIT* jit, FunctionType function,
262 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
263 ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4)
264 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
265 from, jit, function, spillMode, result)
266 , m_argument1(argument1)
267 , m_argument2(argument2)
268 , m_argument3(argument3)
269 , m_argument4(argument4)
270 {
271 }
272
273 protected:
274 void generateInternal(SpeculativeJIT* jit)
275 {
276 this->setUp(jit);
277 this->recordCall(
278 jit->callOperation(
279 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
280 m_argument3, m_argument4));
281 this->tearDown(jit);
282 }
283
284 ArgumentType1 m_argument1;
285 ArgumentType2 m_argument2;
286 ArgumentType3 m_argument3;
287 ArgumentType4 m_argument4;
288 };
289
290 template<
291 typename JumpType, typename FunctionType, typename ResultType,
292 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
293 typename ArgumentType4, typename ArgumentType5>
294 class CallResultAndFiveArgumentsSlowPathGenerator
295 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
296 public:
297 CallResultAndFiveArgumentsSlowPathGenerator(
298 JumpType from, SpeculativeJIT* jit, FunctionType function,
299 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
300 ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4,
301 ArgumentType5 argument5)
302 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
303 from, jit, function, spillMode, result)
304 , m_argument1(argument1)
305 , m_argument2(argument2)
306 , m_argument3(argument3)
307 , m_argument4(argument4)
308 , m_argument5(argument5)
309 {
310 }
311
312 protected:
313 void generateInternal(SpeculativeJIT* jit)
314 {
315 this->setUp(jit);
316 this->recordCall(
317 jit->callOperation(
318 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
319 m_argument3, m_argument4, m_argument5));
320 this->tearDown(jit);
321 }
322
323 ArgumentType1 m_argument1;
324 ArgumentType2 m_argument2;
325 ArgumentType3 m_argument3;
326 ArgumentType4 m_argument4;
327 ArgumentType5 m_argument5;
328 };
329
330 template<typename JumpType, typename FunctionType, typename ResultType>
331 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
332 JumpType from, SpeculativeJIT* jit, FunctionType function,
333 ResultType result, SpillRegistersMode spillMode = NeedToSpill)
334 {
335 return std::make_unique<CallResultAndNoArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType>>(
336 from, jit, function, spillMode, result);
337 }
338
339 template<
340 typename JumpType, typename FunctionType, typename ResultType,
341 typename ArgumentType1>
342 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
343 JumpType from, SpeculativeJIT* jit, FunctionType function,
344 ResultType result, ArgumentType1 argument1,
345 SpillRegistersMode spillMode = NeedToSpill)
346 {
347 return std::make_unique<CallResultAndOneArgumentSlowPathGenerator<JumpType, FunctionType, ResultType, ArgumentType1>>(
348 from, jit, function, spillMode, result, argument1);
349 }
350
351 template<
352 typename JumpType, typename FunctionType, typename ResultType,
353 typename ArgumentType1, typename ArgumentType2>
354 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
355 JumpType from, SpeculativeJIT* jit, FunctionType function,
356 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
357 SpillRegistersMode spillMode = NeedToSpill)
358 {
359 return std::make_unique<CallResultAndTwoArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2>>(
360 from, jit, function, spillMode, result, argument1, argument2);
361 }
362
363 template<
364 typename JumpType, typename FunctionType, typename ResultType,
365 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
366 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
367 JumpType from, SpeculativeJIT* jit, FunctionType function,
368 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
369 ArgumentType3 argument3, SpillRegistersMode spillMode = NeedToSpill)
370 {
371 return std::make_unique<CallResultAndThreeArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
372 ArgumentType3>>(from, jit, function, spillMode, result, argument1, argument2, argument3);
373 }
374
375 template<
376 typename JumpType, typename FunctionType, typename ResultType,
377 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
378 typename ArgumentType4>
379 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
380 JumpType from, SpeculativeJIT* jit, FunctionType function,
381 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
382 ArgumentType3 argument3, ArgumentType4 argument4,
383 SpillRegistersMode spillMode = NeedToSpill)
384 {
385 return std::make_unique<CallResultAndFourArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
386 ArgumentType3, ArgumentType4>>(from, jit, function, spillMode, result, argument1, argument2, argument3, argument4);
387 }
388
389 template<
390 typename JumpType, typename FunctionType, typename ResultType,
391 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
392 typename ArgumentType4, typename ArgumentType5>
393 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
394 JumpType from, SpeculativeJIT* jit, FunctionType function,
395 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
396 ArgumentType3 argument3, ArgumentType4 argument4, ArgumentType5 argument5,
397 SpillRegistersMode spillMode = NeedToSpill)
398 {
399 return std::make_unique<CallResultAndFiveArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
400 ArgumentType3, ArgumentType4, ArgumentType5>>(from, jit, function, spillMode, result, argument1, argument2, argument3,
401 argument4, argument5);
402 }
403
404 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
405 class AssigningSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
406 public:
407 AssigningSlowPathGenerator(
408 JumpType from, SpeculativeJIT* jit,
409 DestinationType destination[numberOfAssignments],
410 SourceType source[numberOfAssignments])
411 : JumpingSlowPathGenerator<JumpType>(from, jit)
412 {
413 for (unsigned i = numberOfAssignments; i--;) {
414 m_destination[i] = destination[i];
415 m_source[i] = source[i];
416 }
417 }
418
419 protected:
420 virtual void generateInternal(SpeculativeJIT* jit) override
421 {
422 this->linkFrom(jit);
423 for (unsigned i = numberOfAssignments; i--;)
424 jit->m_jit.move(m_source[i], m_destination[i]);
425 this->jumpTo(jit);
426 }
427
428 private:
429 DestinationType m_destination[numberOfAssignments];
430 SourceType m_source[numberOfAssignments];
431 };
432
433 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
434 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
435 JumpType from, SpeculativeJIT* jit, SourceType source[numberOfAssignments], DestinationType destination[numberOfAssignments])
436 {
437 return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, numberOfAssignments>>(
438 from, jit, destination, source);
439 }
440
441 template<typename JumpType, typename DestinationType, typename SourceType>
442 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
443 JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
444 {
445 SourceType sourceArray[1] = { source };
446 DestinationType destinationArray[1] = { destination };
447 return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 1>>(
448 from, jit, destinationArray, sourceArray);
449 }
450
451 template<typename JumpType, typename DestinationType, typename SourceType>
452 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
453 JumpType from, SpeculativeJIT* jit, SourceType source1, DestinationType destination1, SourceType source2, DestinationType destination2)
454 {
455 SourceType sourceArray[2] = { source1, source2 };
456 DestinationType destinationArray[2] = { destination1, destination2 };
457 return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 2>>(
458 from, jit, destinationArray, sourceArray);
459 }
460
461 } } // namespace JSC::DFG
462
463 #endif // ENABLD(DFG_JIT)
464
465 #endif // DFGSlowPathGenerator_h
466