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
31 #include "DFGCommon.h"
32 #include "DFGSilentRegisterSavePlan.h"
33 #include "DFGSpeculativeJIT.h"
34 #include <wtf/FastMalloc.h>
35 #include <wtf/PassOwnPtr.h>
37 namespace JSC
{ namespace DFG
{
39 class SlowPathGenerator
{
40 WTF_MAKE_FAST_ALLOCATED
;
42 SlowPathGenerator(SpeculativeJIT
* jit
)
43 : m_currentNode(jit
->m_currentNode
)
46 virtual ~SlowPathGenerator() { }
47 void generate(SpeculativeJIT
* jit
)
49 m_label
= jit
->m_jit
.label();
50 jit
->m_currentNode
= m_currentNode
;
51 generateInternal(jit
);
53 jit
->m_jit
.abortWithReason(DFGSlowPathGeneratorFellThrough
);
55 MacroAssembler::Label
label() const { return m_label
; }
56 virtual MacroAssembler::Call
call() const
58 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
59 return MacroAssembler::Call();
62 virtual void generateInternal(SpeculativeJIT
*) = 0;
63 MacroAssembler::Label m_label
;
67 template<typename JumpType
>
68 class JumpingSlowPathGenerator
: public SlowPathGenerator
{
70 JumpingSlowPathGenerator(JumpType from
, SpeculativeJIT
* jit
)
71 : SlowPathGenerator(jit
)
73 , m_to(jit
->m_jit
.label())
78 void linkFrom(SpeculativeJIT
* jit
)
80 m_from
.link(&jit
->m_jit
);
83 void jumpTo(SpeculativeJIT
* jit
)
85 jit
->m_jit
.jump().linkTo(m_to
, &jit
->m_jit
);
89 MacroAssembler::Label m_to
;
92 template<typename JumpType
, typename FunctionType
, typename ResultType
>
93 class CallSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
95 CallSlowPathGenerator(
96 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
97 SpillRegistersMode spillMode
, ResultType result
)
98 : JumpingSlowPathGenerator
<JumpType
>(from
, jit
)
99 , m_function(function
)
100 , m_spillMode(spillMode
)
103 if (m_spillMode
== NeedToSpill
)
104 jit
->silentSpillAllRegistersImpl(false, m_plans
, extractResult(result
));
107 virtual MacroAssembler::Call
call() const override
113 void setUp(SpeculativeJIT
* jit
)
116 if (m_spillMode
== NeedToSpill
) {
117 for (unsigned i
= 0; i
< m_plans
.size(); ++i
)
118 jit
->silentSpill(m_plans
[i
]);
122 void recordCall(MacroAssembler::Call call
)
127 void tearDown(SpeculativeJIT
* jit
)
129 if (m_spillMode
== NeedToSpill
) {
130 GPRReg canTrample
= SpeculativeJIT::pickCanTrample(extractResult(m_result
));
131 for (unsigned i
= m_plans
.size(); i
--;)
132 jit
->silentFill(m_plans
[i
], canTrample
);
137 FunctionType m_function
;
138 SpillRegistersMode m_spillMode
;
140 MacroAssembler::Call m_call
;
141 Vector
<SilentRegisterSavePlan
, 2> m_plans
;
144 template<typename JumpType
, typename FunctionType
, typename ResultType
>
145 class CallResultAndNoArgumentsSlowPathGenerator
146 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
148 CallResultAndNoArgumentsSlowPathGenerator(
149 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
150 SpillRegistersMode spillMode
, ResultType result
)
151 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
152 from
, jit
, function
, spillMode
, result
)
157 virtual void generateInternal(SpeculativeJIT
* jit
) override
160 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
)));
166 typename JumpType
, typename FunctionType
, typename ResultType
,
167 typename ArgumentType1
>
168 class CallResultAndOneArgumentSlowPathGenerator
169 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
171 CallResultAndOneArgumentSlowPathGenerator(
172 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
173 SpillRegistersMode spillMode
, ResultType result
, ArgumentType1 argument1
)
174 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
175 from
, jit
, function
, spillMode
, result
)
176 , m_argument1(argument1
)
181 virtual void generateInternal(SpeculativeJIT
* jit
) override
184 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
), m_argument1
));
188 ArgumentType1 m_argument1
;
192 typename JumpType
, typename FunctionType
, typename ResultType
,
193 typename ArgumentType1
, typename ArgumentType2
>
194 class CallResultAndTwoArgumentsSlowPathGenerator
195 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
197 CallResultAndTwoArgumentsSlowPathGenerator(
198 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
199 SpillRegistersMode spillMode
, ResultType result
, ArgumentType1 argument1
,
200 ArgumentType2 argument2
)
201 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
202 from
, jit
, function
, spillMode
, result
)
203 , m_argument1(argument1
)
204 , m_argument2(argument2
)
209 virtual void generateInternal(SpeculativeJIT
* jit
) override
212 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
));
216 ArgumentType1 m_argument1
;
217 ArgumentType2 m_argument2
;
221 typename JumpType
, typename FunctionType
, typename ResultType
,
222 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
>
223 class CallResultAndThreeArgumentsSlowPathGenerator
224 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
226 CallResultAndThreeArgumentsSlowPathGenerator(
227 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
228 SpillRegistersMode spillMode
, ResultType result
, ArgumentType1 argument1
,
229 ArgumentType2 argument2
, ArgumentType3 argument3
)
230 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
231 from
, jit
, function
, spillMode
, result
)
232 , m_argument1(argument1
)
233 , m_argument2(argument2
)
234 , m_argument3(argument3
)
239 virtual void generateInternal(SpeculativeJIT
* jit
) override
244 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
249 ArgumentType1 m_argument1
;
250 ArgumentType2 m_argument2
;
251 ArgumentType3 m_argument3
;
255 typename JumpType
, typename FunctionType
, typename ResultType
,
256 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
,
257 typename ArgumentType4
>
258 class CallResultAndFourArgumentsSlowPathGenerator
259 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
261 CallResultAndFourArgumentsSlowPathGenerator(
262 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
263 SpillRegistersMode spillMode
, ResultType result
, ArgumentType1 argument1
,
264 ArgumentType2 argument2
, ArgumentType3 argument3
, ArgumentType4 argument4
)
265 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
266 from
, jit
, function
, spillMode
, result
)
267 , m_argument1(argument1
)
268 , m_argument2(argument2
)
269 , m_argument3(argument3
)
270 , m_argument4(argument4
)
275 void generateInternal(SpeculativeJIT
* jit
)
280 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
281 m_argument3
, m_argument4
));
285 ArgumentType1 m_argument1
;
286 ArgumentType2 m_argument2
;
287 ArgumentType3 m_argument3
;
288 ArgumentType4 m_argument4
;
292 typename JumpType
, typename FunctionType
, typename ResultType
,
293 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
,
294 typename ArgumentType4
, typename ArgumentType5
>
295 class CallResultAndFiveArgumentsSlowPathGenerator
296 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
298 CallResultAndFiveArgumentsSlowPathGenerator(
299 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
300 SpillRegistersMode spillMode
, ResultType result
, ArgumentType1 argument1
,
301 ArgumentType2 argument2
, ArgumentType3 argument3
, ArgumentType4 argument4
,
302 ArgumentType5 argument5
)
303 : CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>(
304 from
, jit
, function
, spillMode
, result
)
305 , m_argument1(argument1
)
306 , m_argument2(argument2
)
307 , m_argument3(argument3
)
308 , m_argument4(argument4
)
309 , m_argument5(argument5
)
314 void generateInternal(SpeculativeJIT
* jit
)
319 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
320 m_argument3
, m_argument4
, m_argument5
));
324 ArgumentType1 m_argument1
;
325 ArgumentType2 m_argument2
;
326 ArgumentType3 m_argument3
;
327 ArgumentType4 m_argument4
;
328 ArgumentType5 m_argument5
;
331 template<typename JumpType
, typename FunctionType
, typename ResultType
>
332 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
333 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
334 ResultType result
, SpillRegistersMode spillMode
= NeedToSpill
)
337 new CallResultAndNoArgumentsSlowPathGenerator
<
338 JumpType
, FunctionType
, ResultType
>(
339 from
, jit
, function
, spillMode
, result
));
343 typename JumpType
, typename FunctionType
, typename ResultType
,
344 typename ArgumentType1
>
345 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
346 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
347 ResultType result
, ArgumentType1 argument1
,
348 SpillRegistersMode spillMode
= NeedToSpill
)
351 new CallResultAndOneArgumentSlowPathGenerator
<
352 JumpType
, FunctionType
, ResultType
, ArgumentType1
>(
353 from
, jit
, function
, spillMode
, result
, argument1
));
357 typename JumpType
, typename FunctionType
, typename ResultType
,
358 typename ArgumentType1
, typename ArgumentType2
>
359 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
360 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
361 ResultType result
, ArgumentType1 argument1
, ArgumentType2 argument2
,
362 SpillRegistersMode spillMode
= NeedToSpill
)
365 new CallResultAndTwoArgumentsSlowPathGenerator
<
366 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
>(
367 from
, jit
, function
, spillMode
, result
, argument1
, argument2
));
371 typename JumpType
, typename FunctionType
, typename ResultType
,
372 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
>
373 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
374 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
375 ResultType result
, ArgumentType1 argument1
, ArgumentType2 argument2
,
376 ArgumentType3 argument3
, SpillRegistersMode spillMode
= NeedToSpill
)
379 new CallResultAndThreeArgumentsSlowPathGenerator
<
380 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
382 from
, jit
, function
, spillMode
, result
, argument1
, argument2
,
387 typename JumpType
, typename FunctionType
, typename ResultType
,
388 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
,
389 typename ArgumentType4
>
390 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
391 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
392 ResultType result
, ArgumentType1 argument1
, ArgumentType2 argument2
,
393 ArgumentType3 argument3
, ArgumentType4 argument4
,
394 SpillRegistersMode spillMode
= NeedToSpill
)
397 new CallResultAndFourArgumentsSlowPathGenerator
<
398 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
399 ArgumentType3
, ArgumentType4
>(
400 from
, jit
, function
, spillMode
, result
, argument1
, argument2
,
401 argument3
, argument4
));
405 typename JumpType
, typename FunctionType
, typename ResultType
,
406 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
,
407 typename ArgumentType4
, typename ArgumentType5
>
408 inline PassOwnPtr
<SlowPathGenerator
> slowPathCall(
409 JumpType from
, SpeculativeJIT
* jit
, FunctionType function
,
410 ResultType result
, ArgumentType1 argument1
, ArgumentType2 argument2
,
411 ArgumentType3 argument3
, ArgumentType4 argument4
, ArgumentType5 argument5
,
412 SpillRegistersMode spillMode
= NeedToSpill
)
415 new CallResultAndFiveArgumentsSlowPathGenerator
<
416 JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
417 ArgumentType3
, ArgumentType4
, ArgumentType5
>(
418 from
, jit
, function
, spillMode
, result
, argument1
, argument2
,
419 argument3
, argument4
, argument5
));
422 template<typename JumpType
, typename DestinationType
, typename SourceType
, unsigned numberOfAssignments
>
423 class AssigningSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
425 AssigningSlowPathGenerator(
426 JumpType from
, SpeculativeJIT
* jit
,
427 DestinationType destination
[numberOfAssignments
],
428 SourceType source
[numberOfAssignments
])
429 : JumpingSlowPathGenerator
<JumpType
>(from
, jit
)
431 for (unsigned i
= numberOfAssignments
; i
--;) {
432 m_destination
[i
] = destination
[i
];
433 m_source
[i
] = source
[i
];
438 virtual void generateInternal(SpeculativeJIT
* jit
) override
441 for (unsigned i
= numberOfAssignments
; i
--;)
442 jit
->m_jit
.move(m_source
[i
], m_destination
[i
]);
447 DestinationType m_destination
[numberOfAssignments
];
448 SourceType m_source
[numberOfAssignments
];
451 template<typename JumpType
, typename DestinationType
, typename SourceType
, unsigned numberOfAssignments
>
452 inline PassOwnPtr
<SlowPathGenerator
> slowPathMove(
453 JumpType from
, SpeculativeJIT
* jit
, SourceType source
[numberOfAssignments
], DestinationType destination
[numberOfAssignments
])
456 new AssigningSlowPathGenerator
<
457 JumpType
, DestinationType
, SourceType
, numberOfAssignments
>(
458 from
, jit
, destination
, source
));
461 template<typename JumpType
, typename DestinationType
, typename SourceType
>
462 inline PassOwnPtr
<SlowPathGenerator
> slowPathMove(
463 JumpType from
, SpeculativeJIT
* jit
, SourceType source
, DestinationType destination
)
465 SourceType sourceArray
[1] = { source
};
466 DestinationType destinationArray
[1] = { destination
};
468 new AssigningSlowPathGenerator
<
469 JumpType
, DestinationType
, SourceType
, 1>(
470 from
, jit
, destinationArray
, sourceArray
));
473 template<typename JumpType
, typename DestinationType
, typename SourceType
>
474 inline PassOwnPtr
<SlowPathGenerator
> slowPathMove(
475 JumpType from
, SpeculativeJIT
* jit
, SourceType source1
, DestinationType destination1
, SourceType source2
, DestinationType destination2
)
477 SourceType sourceArray
[2] = { source1
, source2
};
478 DestinationType destinationArray
[2] = { destination1
, destination2
};
480 new AssigningSlowPathGenerator
<
481 JumpType
, DestinationType
, SourceType
, 2>(
482 from
, jit
, destinationArray
, sourceArray
));
485 } } // namespace JSC::DFG
487 #endif // ENABLD(DFG_JIT)
489 #endif // DFGSlowPathGenerator_h