2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef DFGSlowPathGenerator_h
27 #define DFGSlowPathGenerator_h
29 #include <wtf/Platform.h>
33 #include "DFGCommon.h"
34 #include "DFGSilentRegisterSavePlan.h"
35 #include "DFGSpeculativeJIT.h"
36 #include <wtf/FastAllocBase.h>
37 #include <wtf/PassOwnPtr.h>
39 namespace JSC
{ namespace DFG
{
41 class SlowPathGenerator
{
42 WTF_MAKE_FAST_ALLOCATED
;
44 SlowPathGenerator(SpeculativeJIT
* jit
)
45 : m_currentNode(jit
->m_currentNode
)
48 virtual ~SlowPathGenerator() { }
49 void generate(SpeculativeJIT
* jit
)
51 #if DFG_ENABLE(DEBUG_VERBOSE)
52 dataLogF("Generating slow path %p at offset 0x%x\n", this, jit
->m_jit
.debugOffset());
54 m_label
= jit
->m_jit
.label();
55 jit
->m_currentNode
= m_currentNode
;
56 generateInternal(jit
);
58 jit
->m_jit
.breakpoint(); // make sure that the generator jumps back to somewhere
61 MacroAssembler::Label
label() const { return m_label
; }
62 virtual MacroAssembler::Call
call() const
64 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
65 return MacroAssembler::Call();
68 virtual void generateInternal(SpeculativeJIT
*) = 0;
69 MacroAssembler::Label m_label
;
73 template<typename JumpType
>
74 class JumpingSlowPathGenerator
: public SlowPathGenerator
{
76 JumpingSlowPathGenerator(JumpType from
, SpeculativeJIT
* jit
)
77 : SlowPathGenerator(jit
)
79 , m_to(jit
->m_jit
.label())
84 void linkFrom(SpeculativeJIT
* jit
)
86 m_from
.link(&jit
->m_jit
);
89 void jumpTo(SpeculativeJIT
* jit
)
91 jit
->m_jit
.jump().linkTo(m_to
, &jit
->m_jit
);
95 MacroAssembler::Label m_to
;
98 template<typename JumpType
, typename FunctionType
, typename ResultType
>
99 class CallSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
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
)
109 if (m_spillMode
== NeedToSpill
)
110 jit
->silentSpillAllRegistersImpl(false, m_plans
, result
);
113 virtual MacroAssembler::Call
call() const
119 void setUp(SpeculativeJIT
* jit
)
122 if (m_spillMode
== NeedToSpill
) {
123 for (unsigned i
= 0; i
< m_plans
.size(); ++i
)
124 jit
->silentSpill(m_plans
[i
]);
128 void recordCall(MacroAssembler::Call call
)
133 void tearDown(SpeculativeJIT
* jit
)
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
);
143 FunctionType m_function
;
144 SpillRegistersMode m_spillMode
;
146 MacroAssembler::Call m_call
;
147 Vector
<SilentRegisterSavePlan
, 2> m_plans
;
150 template<typename JumpType
, typename FunctionType
, typename ResultType
>
151 class CallResultAndNoArgumentsSlowPathGenerator
152 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
163 void generateInternal(SpeculativeJIT
* jit
)
166 this->recordCall(jit
->callOperation(this->m_function
, this->m_result
));
172 typename JumpType
, typename FunctionType
, typename ResultType
,
173 typename ArgumentType1
>
174 class CallResultAndOneArgumentSlowPathGenerator
175 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
187 void generateInternal(SpeculativeJIT
* jit
)
190 this->recordCall(jit
->callOperation(this->m_function
, this->m_result
, m_argument1
));
194 ArgumentType1 m_argument1
;
198 typename JumpType
, typename FunctionType
, typename ResultType
,
199 typename ArgumentType1
, typename ArgumentType2
>
200 class CallResultAndTwoArgumentsSlowPathGenerator
201 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
215 void generateInternal(SpeculativeJIT
* jit
)
218 this->recordCall(jit
->callOperation(this->m_function
, this->m_result
, m_argument1
, m_argument2
));
222 ArgumentType1 m_argument1
;
223 ArgumentType2 m_argument2
;
227 typename JumpType
, typename FunctionType
, typename ResultType
,
228 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
>
229 class CallResultAndThreeArgumentsSlowPathGenerator
230 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
245 void generateInternal(SpeculativeJIT
* jit
)
250 this->m_function
, this->m_result
, m_argument1
, m_argument2
,
255 ArgumentType1 m_argument1
;
256 ArgumentType2 m_argument2
;
257 ArgumentType3 m_argument3
;
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
> {
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
)
281 void generateInternal(SpeculativeJIT
* jit
)
286 this->m_function
, this->m_result
, m_argument1
, m_argument2
,
287 m_argument3
, m_argument4
));
291 ArgumentType1 m_argument1
;
292 ArgumentType2 m_argument2
;
293 ArgumentType3 m_argument3
;
294 ArgumentType4 m_argument4
;
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
> {
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
)
320 void generateInternal(SpeculativeJIT
* jit
)
325 this->m_function
, this->m_result
, m_argument1
, m_argument2
,
326 m_argument3
, m_argument4
, m_argument5
));
330 ArgumentType1 m_argument1
;
331 ArgumentType2 m_argument2
;
332 ArgumentType3 m_argument3
;
333 ArgumentType4 m_argument4
;
334 ArgumentType5 m_argument5
;
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
)
343 new CallResultAndNoArgumentsSlowPathGenerator
<
344 JumpType
, FunctionType
, ResultType
>(
345 from
, jit
, function
, spillMode
, result
));
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
)
357 new CallResultAndOneArgumentSlowPathGenerator
<
358 JumpType
, FunctionType
, ResultType
, ArgumentType1
>(
359 from
, jit
, function
, spillMode
, result
, argument1
));
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
)
371 new CallResultAndTwoArgumentsSlowPathGenerator
<
372 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
>(
373 from
, jit
, function
, spillMode
, result
, argument1
, argument2
));
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
)
385 new CallResultAndThreeArgumentsSlowPathGenerator
<
386 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
388 from
, jit
, function
, spillMode
, result
, argument1
, argument2
,
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
)
403 new CallResultAndFourArgumentsSlowPathGenerator
<
404 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
405 ArgumentType3
, ArgumentType4
>(
406 from
, jit
, function
, spillMode
, result
, argument1
, argument2
,
407 argument3
, argument4
));
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
)
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
));
428 template<typename JumpType
, typename DestinationType
, typename SourceType
, unsigned numberOfAssignments
>
429 class AssigningSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
431 AssigningSlowPathGenerator(
432 JumpType from
, SpeculativeJIT
* jit
,
433 DestinationType destination
[numberOfAssignments
],
434 SourceType source
[numberOfAssignments
])
435 : JumpingSlowPathGenerator
<JumpType
>(from
, jit
)
437 for (unsigned i
= numberOfAssignments
; i
--;) {
438 m_destination
[i
] = destination
[i
];
439 m_source
[i
] = source
[i
];
444 virtual void generateInternal(SpeculativeJIT
* jit
)
447 for (unsigned i
= numberOfAssignments
; i
--;)
448 jit
->m_jit
.move(m_source
[i
], m_destination
[i
]);
453 DestinationType m_destination
[numberOfAssignments
];
454 SourceType m_source
[numberOfAssignments
];
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
])
462 new AssigningSlowPathGenerator
<
463 JumpType
, DestinationType
, SourceType
, numberOfAssignments
>(
464 from
, jit
, destination
, source
));
467 template<typename JumpType
, typename DestinationType
, typename SourceType
>
468 inline PassOwnPtr
<SlowPathGenerator
> slowPathMove(
469 JumpType from
, SpeculativeJIT
* jit
, SourceType source
, DestinationType destination
)
471 SourceType sourceArray
[1] = { source
};
472 DestinationType destinationArray
[1] = { destination
};
474 new AssigningSlowPathGenerator
<
475 JumpType
, DestinationType
, SourceType
, 1>(
476 from
, jit
, destinationArray
, sourceArray
));
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
)
483 SourceType sourceArray
[2] = { source1
, source2
};
484 DestinationType destinationArray
[2] = { destination1
, destination2
};
486 new AssigningSlowPathGenerator
<
487 JumpType
, DestinationType
, SourceType
, 2>(
488 from
, jit
, destinationArray
, sourceArray
));
491 } } // namespace JSC::DFG
493 #endif // ENABLD(DFG_JIT)
495 #endif // DFGSlowPathGenerator_h