]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGSlowPathGenerator.h
JavaScriptCore-1218.33.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 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "DFGCommon.h"
34 #include "DFGSilentRegisterSavePlan.h"
35 #include "DFGSpeculativeJIT.h"
36 #include <wtf/FastAllocBase.h>
37 #include <wtf/PassOwnPtr.h>
38
39 namespace JSC { namespace DFG {
40
41 class SlowPathGenerator {
42 WTF_MAKE_FAST_ALLOCATED;
43 public:
44 SlowPathGenerator(SpeculativeJIT* jit)
45 : m_currentNode(jit->m_currentNode)
46 {
47 }
48 virtual ~SlowPathGenerator() { }
49 void generate(SpeculativeJIT* jit)
50 {
51 #if DFG_ENABLE(DEBUG_VERBOSE)
52 dataLogF("Generating slow path %p at offset 0x%x\n", this, jit->m_jit.debugOffset());
53 #endif
54 m_label = jit->m_jit.label();
55 jit->m_currentNode = m_currentNode;
56 generateInternal(jit);
57 #if !ASSERT_DISABLED
58 jit->m_jit.breakpoint(); // make sure that the generator jumps back to somewhere
59 #endif
60 }
61 MacroAssembler::Label label() const { return m_label; }
62 virtual MacroAssembler::Call call() const
63 {
64 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
65 return MacroAssembler::Call();
66 }
67 protected:
68 virtual void generateInternal(SpeculativeJIT*) = 0;
69 MacroAssembler::Label m_label;
70 Node* m_currentNode;
71 };
72
73 template<typename JumpType>
74 class JumpingSlowPathGenerator : public SlowPathGenerator {
75 public:
76 JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
77 : SlowPathGenerator(jit)
78 , m_from(from)
79 , m_to(jit->m_jit.label())
80 {
81 }
82
83 protected:
84 void linkFrom(SpeculativeJIT* jit)
85 {
86 m_from.link(&jit->m_jit);
87 }
88
89 void jumpTo(SpeculativeJIT* jit)
90 {
91 jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
92 }
93
94 JumpType m_from;
95 MacroAssembler::Label m_to;
96 };
97
98 template<typename JumpType, typename FunctionType, typename ResultType>
99 class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
100 public:
101 CallSlowPathGenerator(
102 JumpType from, SpeculativeJIT* jit, FunctionType function,
103 SpillRegistersMode spillMode, ResultType result)
104 : JumpingSlowPathGenerator<JumpType>(from, jit)
105 , m_function(function)
106 , m_spillMode(spillMode)
107 , m_result(result)
108 {
109 if (m_spillMode == NeedToSpill)
110 jit->silentSpillAllRegistersImpl(false, m_plans, result);
111 }
112
113 virtual MacroAssembler::Call call() const
114 {
115 return m_call;
116 }
117
118 protected:
119 void setUp(SpeculativeJIT* jit)
120 {
121 this->linkFrom(jit);
122 if (m_spillMode == NeedToSpill) {
123 for (unsigned i = 0; i < m_plans.size(); ++i)
124 jit->silentSpill(m_plans[i]);
125 }
126 }
127
128 void recordCall(MacroAssembler::Call call)
129 {
130 m_call = call;
131 }
132
133 void tearDown(SpeculativeJIT* jit)
134 {
135 if (m_spillMode == NeedToSpill) {
136 GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_result);
137 for (unsigned i = m_plans.size(); i--;)
138 jit->silentFill(m_plans[i], canTrample);
139 }
140 this->jumpTo(jit);
141 }
142
143 FunctionType m_function;
144 SpillRegistersMode m_spillMode;
145 ResultType m_result;
146 MacroAssembler::Call m_call;
147 Vector<SilentRegisterSavePlan, 2> m_plans;
148 };
149
150 template<typename JumpType, typename FunctionType, typename ResultType>
151 class CallResultAndNoArgumentsSlowPathGenerator
152 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
153 public:
154 CallResultAndNoArgumentsSlowPathGenerator(
155 JumpType from, SpeculativeJIT* jit, FunctionType function,
156 SpillRegistersMode spillMode, ResultType result)
157 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
158 from, jit, function, spillMode, result)
159 {
160 }
161
162 protected:
163 void generateInternal(SpeculativeJIT* jit)
164 {
165 this->setUp(jit);
166 this->recordCall(jit->callOperation(this->m_function, this->m_result));
167 this->tearDown(jit);
168 }
169 };
170
171 template<
172 typename JumpType, typename FunctionType, typename ResultType,
173 typename ArgumentType1>
174 class CallResultAndOneArgumentSlowPathGenerator
175 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
176 public:
177 CallResultAndOneArgumentSlowPathGenerator(
178 JumpType from, SpeculativeJIT* jit, FunctionType function,
179 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1)
180 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
181 from, jit, function, spillMode, result)
182 , m_argument1(argument1)
183 {
184 }
185
186 protected:
187 void generateInternal(SpeculativeJIT* jit)
188 {
189 this->setUp(jit);
190 this->recordCall(jit->callOperation(this->m_function, this->m_result, m_argument1));
191 this->tearDown(jit);
192 }
193
194 ArgumentType1 m_argument1;
195 };
196
197 template<
198 typename JumpType, typename FunctionType, typename ResultType,
199 typename ArgumentType1, typename ArgumentType2>
200 class CallResultAndTwoArgumentsSlowPathGenerator
201 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
202 public:
203 CallResultAndTwoArgumentsSlowPathGenerator(
204 JumpType from, SpeculativeJIT* jit, FunctionType function,
205 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
206 ArgumentType2 argument2)
207 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
208 from, jit, function, spillMode, result)
209 , m_argument1(argument1)
210 , m_argument2(argument2)
211 {
212 }
213
214 protected:
215 void generateInternal(SpeculativeJIT* jit)
216 {
217 this->setUp(jit);
218 this->recordCall(jit->callOperation(this->m_function, this->m_result, m_argument1, m_argument2));
219 this->tearDown(jit);
220 }
221
222 ArgumentType1 m_argument1;
223 ArgumentType2 m_argument2;
224 };
225
226 template<
227 typename JumpType, typename FunctionType, typename ResultType,
228 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
229 class CallResultAndThreeArgumentsSlowPathGenerator
230 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
231 public:
232 CallResultAndThreeArgumentsSlowPathGenerator(
233 JumpType from, SpeculativeJIT* jit, FunctionType function,
234 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
235 ArgumentType2 argument2, ArgumentType3 argument3)
236 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
237 from, jit, function, spillMode, result)
238 , m_argument1(argument1)
239 , m_argument2(argument2)
240 , m_argument3(argument3)
241 {
242 }
243
244 protected:
245 void generateInternal(SpeculativeJIT* jit)
246 {
247 this->setUp(jit);
248 this->recordCall(
249 jit->callOperation(
250 this->m_function, this->m_result, m_argument1, m_argument2,
251 m_argument3));
252 this->tearDown(jit);
253 }
254
255 ArgumentType1 m_argument1;
256 ArgumentType2 m_argument2;
257 ArgumentType3 m_argument3;
258 };
259
260 template<
261 typename JumpType, typename FunctionType, typename ResultType,
262 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
263 typename ArgumentType4>
264 class CallResultAndFourArgumentsSlowPathGenerator
265 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
266 public:
267 CallResultAndFourArgumentsSlowPathGenerator(
268 JumpType from, SpeculativeJIT* jit, FunctionType function,
269 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
270 ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4)
271 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
272 from, jit, function, spillMode, result)
273 , m_argument1(argument1)
274 , m_argument2(argument2)
275 , m_argument3(argument3)
276 , m_argument4(argument4)
277 {
278 }
279
280 protected:
281 void generateInternal(SpeculativeJIT* jit)
282 {
283 this->setUp(jit);
284 this->recordCall(
285 jit->callOperation(
286 this->m_function, this->m_result, m_argument1, m_argument2,
287 m_argument3, m_argument4));
288 this->tearDown(jit);
289 }
290
291 ArgumentType1 m_argument1;
292 ArgumentType2 m_argument2;
293 ArgumentType3 m_argument3;
294 ArgumentType4 m_argument4;
295 };
296
297 template<
298 typename JumpType, typename FunctionType, typename ResultType,
299 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
300 typename ArgumentType4, typename ArgumentType5>
301 class CallResultAndFiveArgumentsSlowPathGenerator
302 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
303 public:
304 CallResultAndFiveArgumentsSlowPathGenerator(
305 JumpType from, SpeculativeJIT* jit, FunctionType function,
306 SpillRegistersMode spillMode, ResultType result, ArgumentType1 argument1,
307 ArgumentType2 argument2, ArgumentType3 argument3, ArgumentType4 argument4,
308 ArgumentType5 argument5)
309 : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
310 from, jit, function, spillMode, result)
311 , m_argument1(argument1)
312 , m_argument2(argument2)
313 , m_argument3(argument3)
314 , m_argument4(argument4)
315 , m_argument5(argument5)
316 {
317 }
318
319 protected:
320 void generateInternal(SpeculativeJIT* jit)
321 {
322 this->setUp(jit);
323 this->recordCall(
324 jit->callOperation(
325 this->m_function, this->m_result, m_argument1, m_argument2,
326 m_argument3, m_argument4, m_argument5));
327 this->tearDown(jit);
328 }
329
330 ArgumentType1 m_argument1;
331 ArgumentType2 m_argument2;
332 ArgumentType3 m_argument3;
333 ArgumentType4 m_argument4;
334 ArgumentType5 m_argument5;
335 };
336
337 template<typename JumpType, typename FunctionType, typename ResultType>
338 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
339 JumpType from, SpeculativeJIT* jit, FunctionType function,
340 ResultType result, SpillRegistersMode spillMode = NeedToSpill)
341 {
342 return adoptPtr(
343 new CallResultAndNoArgumentsSlowPathGenerator<
344 JumpType, FunctionType, ResultType>(
345 from, jit, function, spillMode, result));
346 }
347
348 template<
349 typename JumpType, typename FunctionType, typename ResultType,
350 typename ArgumentType1>
351 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
352 JumpType from, SpeculativeJIT* jit, FunctionType function,
353 ResultType result, ArgumentType1 argument1,
354 SpillRegistersMode spillMode = NeedToSpill)
355 {
356 return adoptPtr(
357 new CallResultAndOneArgumentSlowPathGenerator<
358 JumpType, FunctionType, ResultType, ArgumentType1>(
359 from, jit, function, spillMode, result, argument1));
360 }
361
362 template<
363 typename JumpType, typename FunctionType, typename ResultType,
364 typename ArgumentType1, typename ArgumentType2>
365 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
366 JumpType from, SpeculativeJIT* jit, FunctionType function,
367 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
368 SpillRegistersMode spillMode = NeedToSpill)
369 {
370 return adoptPtr(
371 new CallResultAndTwoArgumentsSlowPathGenerator<
372 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2>(
373 from, jit, function, spillMode, result, argument1, argument2));
374 }
375
376 template<
377 typename JumpType, typename FunctionType, typename ResultType,
378 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
379 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
380 JumpType from, SpeculativeJIT* jit, FunctionType function,
381 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
382 ArgumentType3 argument3, SpillRegistersMode spillMode = NeedToSpill)
383 {
384 return adoptPtr(
385 new CallResultAndThreeArgumentsSlowPathGenerator<
386 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
387 ArgumentType3>(
388 from, jit, function, spillMode, result, argument1, argument2,
389 argument3));
390 }
391
392 template<
393 typename JumpType, typename FunctionType, typename ResultType,
394 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
395 typename ArgumentType4>
396 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
397 JumpType from, SpeculativeJIT* jit, FunctionType function,
398 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
399 ArgumentType3 argument3, ArgumentType4 argument4,
400 SpillRegistersMode spillMode = NeedToSpill)
401 {
402 return adoptPtr(
403 new CallResultAndFourArgumentsSlowPathGenerator<
404 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
405 ArgumentType3, ArgumentType4>(
406 from, jit, function, spillMode, result, argument1, argument2,
407 argument3, argument4));
408 }
409
410 template<
411 typename JumpType, typename FunctionType, typename ResultType,
412 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3,
413 typename ArgumentType4, typename ArgumentType5>
414 inline PassOwnPtr<SlowPathGenerator> slowPathCall(
415 JumpType from, SpeculativeJIT* jit, FunctionType function,
416 ResultType result, ArgumentType1 argument1, ArgumentType2 argument2,
417 ArgumentType3 argument3, ArgumentType4 argument4, ArgumentType5 argument5,
418 SpillRegistersMode spillMode = NeedToSpill)
419 {
420 return adoptPtr(
421 new CallResultAndFiveArgumentsSlowPathGenerator<
422 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
423 ArgumentType3, ArgumentType4, ArgumentType5>(
424 from, jit, function, spillMode, result, argument1, argument2,
425 argument3, argument4, argument5));
426 }
427
428 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
429 class AssigningSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
430 public:
431 AssigningSlowPathGenerator(
432 JumpType from, SpeculativeJIT* jit,
433 DestinationType destination[numberOfAssignments],
434 SourceType source[numberOfAssignments])
435 : JumpingSlowPathGenerator<JumpType>(from, jit)
436 {
437 for (unsigned i = numberOfAssignments; i--;) {
438 m_destination[i] = destination[i];
439 m_source[i] = source[i];
440 }
441 }
442
443 protected:
444 virtual void generateInternal(SpeculativeJIT* jit)
445 {
446 this->linkFrom(jit);
447 for (unsigned i = numberOfAssignments; i--;)
448 jit->m_jit.move(m_source[i], m_destination[i]);
449 this->jumpTo(jit);
450 }
451
452 private:
453 DestinationType m_destination[numberOfAssignments];
454 SourceType m_source[numberOfAssignments];
455 };
456
457 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
458 inline PassOwnPtr<SlowPathGenerator> slowPathMove(
459 JumpType from, SpeculativeJIT* jit, SourceType source[numberOfAssignments], DestinationType destination[numberOfAssignments])
460 {
461 return adoptPtr(
462 new AssigningSlowPathGenerator<
463 JumpType, DestinationType, SourceType, numberOfAssignments>(
464 from, jit, destination, source));
465 }
466
467 template<typename JumpType, typename DestinationType, typename SourceType>
468 inline PassOwnPtr<SlowPathGenerator> slowPathMove(
469 JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
470 {
471 SourceType sourceArray[1] = { source };
472 DestinationType destinationArray[1] = { destination };
473 return adoptPtr(
474 new AssigningSlowPathGenerator<
475 JumpType, DestinationType, SourceType, 1>(
476 from, jit, destinationArray, sourceArray));
477 }
478
479 template<typename JumpType, typename DestinationType, typename SourceType>
480 inline PassOwnPtr<SlowPathGenerator> slowPathMove(
481 JumpType from, SpeculativeJIT* jit, SourceType source1, DestinationType destination1, SourceType source2, DestinationType destination2)
482 {
483 SourceType sourceArray[2] = { source1, source2 };
484 DestinationType destinationArray[2] = { destination1, destination2 };
485 return adoptPtr(
486 new AssigningSlowPathGenerator<
487 JumpType, DestinationType, SourceType, 2>(
488 from, jit, destinationArray, sourceArray));
489 }
490
491 } } // namespace JSC::DFG
492
493 #endif // ENABLD(DFG_JIT)
494
495 #endif // DFGSlowPathGenerator_h
496