]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGSlowPathGenerator.h
JavaScriptCore-7600.1.4.15.12.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 #include <wtf/PassOwnPtr.h>
36
37 namespace JSC { namespace DFG {
38
39 class SlowPathGenerator {
40 WTF_MAKE_FAST_ALLOCATED;
41 public:
42 SlowPathGenerator(SpeculativeJIT* jit)
43 : m_currentNode(jit->m_currentNode)
44 {
45 }
46 virtual ~SlowPathGenerator() { }
47 void generate(SpeculativeJIT* jit)
48 {
49 m_label = jit->m_jit.label();
50 jit->m_currentNode = m_currentNode;
51 generateInternal(jit);
52 if (!ASSERT_DISABLED)
53 jit->m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
54 }
55 MacroAssembler::Label label() const { return m_label; }
56 virtual MacroAssembler::Call call() const
57 {
58 RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
59 return MacroAssembler::Call();
60 }
61 protected:
62 virtual void generateInternal(SpeculativeJIT*) = 0;
63 MacroAssembler::Label m_label;
64 Node* m_currentNode;
65 };
66
67 template<typename JumpType>
68 class JumpingSlowPathGenerator : public SlowPathGenerator {
69 public:
70 JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
71 : SlowPathGenerator(jit)
72 , m_from(from)
73 , m_to(jit->m_jit.label())
74 {
75 }
76
77 protected:
78 void linkFrom(SpeculativeJIT* jit)
79 {
80 m_from.link(&jit->m_jit);
81 }
82
83 void jumpTo(SpeculativeJIT* jit)
84 {
85 jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
86 }
87
88 JumpType m_from;
89 MacroAssembler::Label m_to;
90 };
91
92 template<typename JumpType, typename FunctionType, typename ResultType>
93 class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
94 public:
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)
101 , m_result(result)
102 {
103 if (m_spillMode == NeedToSpill)
104 jit->silentSpillAllRegistersImpl(false, m_plans, extractResult(result));
105 }
106
107 virtual MacroAssembler::Call call() const override
108 {
109 return m_call;
110 }
111
112 protected:
113 void setUp(SpeculativeJIT* jit)
114 {
115 this->linkFrom(jit);
116 if (m_spillMode == NeedToSpill) {
117 for (unsigned i = 0; i < m_plans.size(); ++i)
118 jit->silentSpill(m_plans[i]);
119 }
120 }
121
122 void recordCall(MacroAssembler::Call call)
123 {
124 m_call = call;
125 }
126
127 void tearDown(SpeculativeJIT* jit)
128 {
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);
133 }
134 this->jumpTo(jit);
135 }
136
137 FunctionType m_function;
138 SpillRegistersMode m_spillMode;
139 ResultType m_result;
140 MacroAssembler::Call m_call;
141 Vector<SilentRegisterSavePlan, 2> m_plans;
142 };
143
144 template<typename JumpType, typename FunctionType, typename ResultType>
145 class CallResultAndNoArgumentsSlowPathGenerator
146 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
147 public:
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)
153 {
154 }
155
156 protected:
157 virtual void generateInternal(SpeculativeJIT* jit) override
158 {
159 this->setUp(jit);
160 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result)));
161 this->tearDown(jit);
162 }
163 };
164
165 template<
166 typename JumpType, typename FunctionType, typename ResultType,
167 typename ArgumentType1>
168 class CallResultAndOneArgumentSlowPathGenerator
169 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
170 public:
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)
177 {
178 }
179
180 protected:
181 virtual void generateInternal(SpeculativeJIT* jit) override
182 {
183 this->setUp(jit);
184 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), m_argument1));
185 this->tearDown(jit);
186 }
187
188 ArgumentType1 m_argument1;
189 };
190
191 template<
192 typename JumpType, typename FunctionType, typename ResultType,
193 typename ArgumentType1, typename ArgumentType2>
194 class CallResultAndTwoArgumentsSlowPathGenerator
195 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
196 public:
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)
205 {
206 }
207
208 protected:
209 virtual void generateInternal(SpeculativeJIT* jit) override
210 {
211 this->setUp(jit);
212 this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), m_argument1, m_argument2));
213 this->tearDown(jit);
214 }
215
216 ArgumentType1 m_argument1;
217 ArgumentType2 m_argument2;
218 };
219
220 template<
221 typename JumpType, typename FunctionType, typename ResultType,
222 typename ArgumentType1, typename ArgumentType2, typename ArgumentType3>
223 class CallResultAndThreeArgumentsSlowPathGenerator
224 : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
225 public:
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)
235 {
236 }
237
238 protected:
239 virtual void generateInternal(SpeculativeJIT* jit) override
240 {
241 this->setUp(jit);
242 this->recordCall(
243 jit->callOperation(
244 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
245 m_argument3));
246 this->tearDown(jit);
247 }
248
249 ArgumentType1 m_argument1;
250 ArgumentType2 m_argument2;
251 ArgumentType3 m_argument3;
252 };
253
254 template<
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> {
260 public:
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)
271 {
272 }
273
274 protected:
275 void generateInternal(SpeculativeJIT* jit)
276 {
277 this->setUp(jit);
278 this->recordCall(
279 jit->callOperation(
280 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
281 m_argument3, m_argument4));
282 this->tearDown(jit);
283 }
284
285 ArgumentType1 m_argument1;
286 ArgumentType2 m_argument2;
287 ArgumentType3 m_argument3;
288 ArgumentType4 m_argument4;
289 };
290
291 template<
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> {
297 public:
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)
310 {
311 }
312
313 protected:
314 void generateInternal(SpeculativeJIT* jit)
315 {
316 this->setUp(jit);
317 this->recordCall(
318 jit->callOperation(
319 this->m_function, extractResult(this->m_result), m_argument1, m_argument2,
320 m_argument3, m_argument4, m_argument5));
321 this->tearDown(jit);
322 }
323
324 ArgumentType1 m_argument1;
325 ArgumentType2 m_argument2;
326 ArgumentType3 m_argument3;
327 ArgumentType4 m_argument4;
328 ArgumentType5 m_argument5;
329 };
330
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)
335 {
336 return adoptPtr(
337 new CallResultAndNoArgumentsSlowPathGenerator<
338 JumpType, FunctionType, ResultType>(
339 from, jit, function, spillMode, result));
340 }
341
342 template<
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)
349 {
350 return adoptPtr(
351 new CallResultAndOneArgumentSlowPathGenerator<
352 JumpType, FunctionType, ResultType, ArgumentType1>(
353 from, jit, function, spillMode, result, argument1));
354 }
355
356 template<
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)
363 {
364 return adoptPtr(
365 new CallResultAndTwoArgumentsSlowPathGenerator<
366 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2>(
367 from, jit, function, spillMode, result, argument1, argument2));
368 }
369
370 template<
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)
377 {
378 return adoptPtr(
379 new CallResultAndThreeArgumentsSlowPathGenerator<
380 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
381 ArgumentType3>(
382 from, jit, function, spillMode, result, argument1, argument2,
383 argument3));
384 }
385
386 template<
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)
395 {
396 return adoptPtr(
397 new CallResultAndFourArgumentsSlowPathGenerator<
398 JumpType, FunctionType, ResultType, ArgumentType1, ArgumentType2,
399 ArgumentType3, ArgumentType4>(
400 from, jit, function, spillMode, result, argument1, argument2,
401 argument3, argument4));
402 }
403
404 template<
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)
413 {
414 return adoptPtr(
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));
420 }
421
422 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
423 class AssigningSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
424 public:
425 AssigningSlowPathGenerator(
426 JumpType from, SpeculativeJIT* jit,
427 DestinationType destination[numberOfAssignments],
428 SourceType source[numberOfAssignments])
429 : JumpingSlowPathGenerator<JumpType>(from, jit)
430 {
431 for (unsigned i = numberOfAssignments; i--;) {
432 m_destination[i] = destination[i];
433 m_source[i] = source[i];
434 }
435 }
436
437 protected:
438 virtual void generateInternal(SpeculativeJIT* jit) override
439 {
440 this->linkFrom(jit);
441 for (unsigned i = numberOfAssignments; i--;)
442 jit->m_jit.move(m_source[i], m_destination[i]);
443 this->jumpTo(jit);
444 }
445
446 private:
447 DestinationType m_destination[numberOfAssignments];
448 SourceType m_source[numberOfAssignments];
449 };
450
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])
454 {
455 return adoptPtr(
456 new AssigningSlowPathGenerator<
457 JumpType, DestinationType, SourceType, numberOfAssignments>(
458 from, jit, destination, source));
459 }
460
461 template<typename JumpType, typename DestinationType, typename SourceType>
462 inline PassOwnPtr<SlowPathGenerator> slowPathMove(
463 JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
464 {
465 SourceType sourceArray[1] = { source };
466 DestinationType destinationArray[1] = { destination };
467 return adoptPtr(
468 new AssigningSlowPathGenerator<
469 JumpType, DestinationType, SourceType, 1>(
470 from, jit, destinationArray, sourceArray));
471 }
472
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)
476 {
477 SourceType sourceArray[2] = { source1, source2 };
478 DestinationType destinationArray[2] = { destination1, destination2 };
479 return adoptPtr(
480 new AssigningSlowPathGenerator<
481 JumpType, DestinationType, SourceType, 2>(
482 from, jit, destinationArray, sourceArray));
483 }
484
485 } } // namespace JSC::DFG
486
487 #endif // ENABLD(DFG_JIT)
488
489 #endif // DFGSlowPathGenerator_h
490