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>
36 namespace JSC
{ namespace DFG
{
38 class SlowPathGenerator
{
39 WTF_MAKE_FAST_ALLOCATED
;
41 SlowPathGenerator(SpeculativeJIT
* jit
)
42 : m_currentNode(jit
->m_currentNode
)
45 virtual ~SlowPathGenerator() { }
46 void generate(SpeculativeJIT
* jit
)
48 m_label
= jit
->m_jit
.label();
49 jit
->m_currentNode
= m_currentNode
;
50 generateInternal(jit
);
52 jit
->m_jit
.abortWithReason(DFGSlowPathGeneratorFellThrough
);
54 MacroAssembler::Label
label() const { return m_label
; }
55 virtual MacroAssembler::Call
call() const
57 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
58 return MacroAssembler::Call();
61 virtual void generateInternal(SpeculativeJIT
*) = 0;
62 MacroAssembler::Label m_label
;
66 template<typename JumpType
>
67 class JumpingSlowPathGenerator
: public SlowPathGenerator
{
69 JumpingSlowPathGenerator(JumpType from
, SpeculativeJIT
* jit
)
70 : SlowPathGenerator(jit
)
72 , m_to(jit
->m_jit
.label())
77 void linkFrom(SpeculativeJIT
* jit
)
79 m_from
.link(&jit
->m_jit
);
82 void jumpTo(SpeculativeJIT
* jit
)
84 jit
->m_jit
.jump().linkTo(m_to
, &jit
->m_jit
);
88 MacroAssembler::Label m_to
;
91 template<typename JumpType
, typename FunctionType
, typename ResultType
>
92 class CallSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
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
)
102 if (m_spillMode
== NeedToSpill
)
103 jit
->silentSpillAllRegistersImpl(false, m_plans
, extractResult(result
));
106 virtual MacroAssembler::Call
call() const override
112 void setUp(SpeculativeJIT
* jit
)
115 if (m_spillMode
== NeedToSpill
) {
116 for (unsigned i
= 0; i
< m_plans
.size(); ++i
)
117 jit
->silentSpill(m_plans
[i
]);
121 void recordCall(MacroAssembler::Call call
)
126 void tearDown(SpeculativeJIT
* jit
)
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
);
136 FunctionType m_function
;
137 SpillRegistersMode m_spillMode
;
139 MacroAssembler::Call m_call
;
140 Vector
<SilentRegisterSavePlan
, 2> m_plans
;
143 template<typename JumpType
, typename FunctionType
, typename ResultType
>
144 class CallResultAndNoArgumentsSlowPathGenerator
145 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
156 virtual void generateInternal(SpeculativeJIT
* jit
) override
159 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
)));
165 typename JumpType
, typename FunctionType
, typename ResultType
,
166 typename ArgumentType1
>
167 class CallResultAndOneArgumentSlowPathGenerator
168 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
180 virtual void generateInternal(SpeculativeJIT
* jit
) override
183 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
), m_argument1
));
187 ArgumentType1 m_argument1
;
191 typename JumpType
, typename FunctionType
, typename ResultType
,
192 typename ArgumentType1
, typename ArgumentType2
>
193 class CallResultAndTwoArgumentsSlowPathGenerator
194 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
208 virtual void generateInternal(SpeculativeJIT
* jit
) override
211 this->recordCall(jit
->callOperation(this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
));
215 ArgumentType1 m_argument1
;
216 ArgumentType2 m_argument2
;
220 typename JumpType
, typename FunctionType
, typename ResultType
,
221 typename ArgumentType1
, typename ArgumentType2
, typename ArgumentType3
>
222 class CallResultAndThreeArgumentsSlowPathGenerator
223 : public CallSlowPathGenerator
<JumpType
, FunctionType
, ResultType
> {
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
)
238 virtual void generateInternal(SpeculativeJIT
* jit
) override
243 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
248 ArgumentType1 m_argument1
;
249 ArgumentType2 m_argument2
;
250 ArgumentType3 m_argument3
;
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
> {
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
)
274 void generateInternal(SpeculativeJIT
* jit
)
279 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
280 m_argument3
, m_argument4
));
284 ArgumentType1 m_argument1
;
285 ArgumentType2 m_argument2
;
286 ArgumentType3 m_argument3
;
287 ArgumentType4 m_argument4
;
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
> {
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
)
313 void generateInternal(SpeculativeJIT
* jit
)
318 this->m_function
, extractResult(this->m_result
), m_argument1
, m_argument2
,
319 m_argument3
, m_argument4
, m_argument5
));
323 ArgumentType1 m_argument1
;
324 ArgumentType2 m_argument2
;
325 ArgumentType3 m_argument3
;
326 ArgumentType4 m_argument4
;
327 ArgumentType5 m_argument5
;
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
)
335 return std::make_unique
<CallResultAndNoArgumentsSlowPathGenerator
<JumpType
, FunctionType
, ResultType
>>(
336 from
, jit
, function
, spillMode
, result
);
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
)
347 return std::make_unique
<CallResultAndOneArgumentSlowPathGenerator
<JumpType
, FunctionType
, ResultType
, ArgumentType1
>>(
348 from
, jit
, function
, spillMode
, result
, argument1
);
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
)
359 return std::make_unique
<CallResultAndTwoArgumentsSlowPathGenerator
<JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
>>(
360 from
, jit
, function
, spillMode
, result
, argument1
, argument2
);
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
)
371 return std::make_unique
<CallResultAndThreeArgumentsSlowPathGenerator
<JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
372 ArgumentType3
>>(from
, jit
, function
, spillMode
, result
, argument1
, argument2
, argument3
);
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
)
385 return std::make_unique
<CallResultAndFourArgumentsSlowPathGenerator
<JumpType
, FunctionType
, ResultType
, ArgumentType1
, ArgumentType2
,
386 ArgumentType3
, ArgumentType4
>>(from
, jit
, function
, spillMode
, result
, argument1
, argument2
, argument3
, argument4
);
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
)
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
);
404 template<typename JumpType
, typename DestinationType
, typename SourceType
, unsigned numberOfAssignments
>
405 class AssigningSlowPathGenerator
: public JumpingSlowPathGenerator
<JumpType
> {
407 AssigningSlowPathGenerator(
408 JumpType from
, SpeculativeJIT
* jit
,
409 DestinationType destination
[numberOfAssignments
],
410 SourceType source
[numberOfAssignments
])
411 : JumpingSlowPathGenerator
<JumpType
>(from
, jit
)
413 for (unsigned i
= numberOfAssignments
; i
--;) {
414 m_destination
[i
] = destination
[i
];
415 m_source
[i
] = source
[i
];
420 virtual void generateInternal(SpeculativeJIT
* jit
) override
423 for (unsigned i
= numberOfAssignments
; i
--;)
424 jit
->m_jit
.move(m_source
[i
], m_destination
[i
]);
429 DestinationType m_destination
[numberOfAssignments
];
430 SourceType m_source
[numberOfAssignments
];
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
])
437 return std::make_unique
<AssigningSlowPathGenerator
<JumpType
, DestinationType
, SourceType
, numberOfAssignments
>>(
438 from
, jit
, destination
, source
);
441 template<typename JumpType
, typename DestinationType
, typename SourceType
>
442 inline std::unique_ptr
<SlowPathGenerator
> slowPathMove(
443 JumpType from
, SpeculativeJIT
* jit
, SourceType source
, DestinationType destination
)
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
);
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
)
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
);
461 } } // namespace JSC::DFG
463 #endif // ENABLD(DFG_JIT)
465 #endif // DFGSlowPathGenerator_h