Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSlowPathGenerator.h
1 /*
2  * Copyright (C) 2012-2017 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 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "DFGSilentRegisterSavePlan.h"
31 #include "DFGSpeculativeJIT.h"
32 #include <wtf/FastMalloc.h>
33
34 namespace JSC { namespace DFG {
35
36 class SlowPathGenerator {
37     WTF_MAKE_FAST_ALLOCATED;
38 public:
39     SlowPathGenerator(SpeculativeJIT* jit)
40         : m_currentNode(jit->m_currentNode)
41         , m_streamIndex(jit->m_stream->size())
42         , m_origin(jit->m_origin) 
43     {
44     }
45     virtual ~SlowPathGenerator() { }
46     void generate(SpeculativeJIT* jit)
47     {
48         m_label = jit->m_jit.label();
49         jit->m_currentNode = m_currentNode;
50         jit->m_outOfLineStreamIndex = m_streamIndex;
51         jit->m_origin = m_origin;
52         generateInternal(jit);
53         jit->m_outOfLineStreamIndex = std::nullopt;
54         if (!ASSERT_DISABLED)
55             jit->m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
56     }
57     MacroAssembler::Label label() const { return m_label; }
58     virtual MacroAssembler::Call call() const
59     {
60         RELEASE_ASSERT_NOT_REACHED(); // By default slow path generators don't have a call.
61         return MacroAssembler::Call();
62     }
63
64     const NodeOrigin& origin() const  { return m_origin; }
65
66 protected:
67     virtual void generateInternal(SpeculativeJIT*) = 0;
68     MacroAssembler::Label m_label;
69     Node* m_currentNode;
70     unsigned m_streamIndex;
71     NodeOrigin m_origin;
72 };
73
74 template<typename JumpType>
75 class JumpingSlowPathGenerator : public SlowPathGenerator {
76 public:
77     JumpingSlowPathGenerator(JumpType from, SpeculativeJIT* jit)
78         : SlowPathGenerator(jit)
79         , m_from(from)
80         , m_to(jit->m_jit.label())
81     {
82     }
83     
84 protected:
85     void linkFrom(SpeculativeJIT* jit)
86     {
87         m_from.link(&jit->m_jit);
88     }
89     
90     void jumpTo(SpeculativeJIT* jit)
91     {
92         jit->m_jit.jump().linkTo(m_to, &jit->m_jit);
93     }
94
95     JumpType m_from;
96     MacroAssembler::Label m_to;
97 };
98
99 enum class ExceptionCheckRequirement {
100     CheckNeeded,
101     CheckNotNeeded
102 };
103
104 template<typename JumpType, typename FunctionType, typename ResultType>
105 class CallSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
106 public:
107     CallSlowPathGenerator(
108         JumpType from, SpeculativeJIT* jit, FunctionType function,
109         SpillRegistersMode spillMode, ExceptionCheckRequirement requirement, ResultType result)
110         : JumpingSlowPathGenerator<JumpType>(from, jit)
111         , m_function(function)
112         , m_spillMode(spillMode)
113         , m_exceptionCheckRequirement(requirement)
114         , m_result(result)
115     {
116         if (m_spillMode == NeedToSpill)
117             jit->silentSpillAllRegistersImpl(false, m_plans, extractResult(result));
118     }
119     
120     MacroAssembler::Call call() const override
121     {
122         return m_call;
123     }
124     
125 protected:
126     void setUp(SpeculativeJIT* jit)
127     {
128         this->linkFrom(jit);
129         if (m_spillMode == NeedToSpill) {
130             for (unsigned i = 0; i < m_plans.size(); ++i)
131                 jit->silentSpill(m_plans[i]);
132         }
133     }
134     
135     void recordCall(MacroAssembler::Call call)
136     {
137         m_call = call;
138     }
139     
140     void tearDown(SpeculativeJIT* jit)
141     {
142         if (m_spillMode == NeedToSpill) {
143             for (unsigned i = m_plans.size(); i--;)
144                 jit->silentFill(m_plans[i]);
145         }
146         if (m_exceptionCheckRequirement == ExceptionCheckRequirement::CheckNeeded)
147             jit->m_jit.exceptionCheck();
148         this->jumpTo(jit);
149     }
150
151     FunctionType m_function;
152     SpillRegistersMode m_spillMode;
153     ExceptionCheckRequirement m_exceptionCheckRequirement;
154     ResultType m_result;
155     MacroAssembler::Call m_call;
156     Vector<SilentRegisterSavePlan, 2> m_plans;
157 };
158
159 template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
160 class CallResultAndArgumentsSlowPathGenerator
161     : public CallSlowPathGenerator<JumpType, FunctionType, ResultType> {
162 public:
163     CallResultAndArgumentsSlowPathGenerator(
164         JumpType from, SpeculativeJIT* jit, FunctionType function,
165         SpillRegistersMode spillMode, ExceptionCheckRequirement requirement, ResultType result, Arguments... arguments)
166         : CallSlowPathGenerator<JumpType, FunctionType, ResultType>(
167             from, jit, function, spillMode, requirement, result)
168         , m_arguments(std::forward<Arguments>(arguments)...)
169     {
170     }
171
172 protected:
173     template<size_t... ArgumentsIndex>
174     void unpackAndGenerate(SpeculativeJIT* jit, std::index_sequence<ArgumentsIndex...>)
175     {
176         this->setUp(jit);
177         this->recordCall(jit->callOperation(this->m_function, extractResult(this->m_result), std::get<ArgumentsIndex>(m_arguments)...));
178         this->tearDown(jit);
179     }
180
181     void generateInternal(SpeculativeJIT* jit) override
182     {
183         unpackAndGenerate(jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>());
184     }
185
186     std::tuple<Arguments...> m_arguments;
187 };
188
189 template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
190 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
191     JumpType from, SpeculativeJIT* jit, FunctionType function,
192     SpillRegistersMode spillMode, ExceptionCheckRequirement requirement,
193     ResultType result, Arguments... arguments)
194 {
195     return std::make_unique<CallResultAndArgumentsSlowPathGenerator<JumpType, FunctionType, ResultType, Arguments...>>(
196         from, jit, function, spillMode, requirement, result, arguments...);
197 }
198
199 template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
200 inline std::unique_ptr<SlowPathGenerator> slowPathCall(
201     JumpType from, SpeculativeJIT* jit, FunctionType function,
202     ResultType result, Arguments... arguments)
203 {
204     return slowPathCall(
205         from, jit, function, NeedToSpill, ExceptionCheckRequirement::CheckNeeded, result, arguments...);
206 }
207
208 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
209 class AssigningSlowPathGenerator : public JumpingSlowPathGenerator<JumpType> {
210 public:
211     AssigningSlowPathGenerator(
212         JumpType from, SpeculativeJIT* jit,
213         DestinationType destination[numberOfAssignments],
214         SourceType source[numberOfAssignments])
215         : JumpingSlowPathGenerator<JumpType>(from, jit)
216     {
217         for (unsigned i = numberOfAssignments; i--;) {
218             m_destination[i] = destination[i];
219             m_source[i] = source[i];
220         }
221     }
222
223 protected:
224     void generateInternal(SpeculativeJIT* jit) override
225     {
226         this->linkFrom(jit);
227         for (unsigned i = numberOfAssignments; i--;)
228             jit->m_jit.move(m_source[i], m_destination[i]);
229         this->jumpTo(jit);
230     }
231
232 private:
233     DestinationType m_destination[numberOfAssignments];
234     SourceType m_source[numberOfAssignments];
235 };
236
237 template<typename JumpType, typename DestinationType, typename SourceType, unsigned numberOfAssignments>
238 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
239     JumpType from, SpeculativeJIT* jit, SourceType source[numberOfAssignments], DestinationType destination[numberOfAssignments])
240 {
241     return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, numberOfAssignments>>(
242         from, jit, destination, source);
243 }
244
245 template<typename JumpType, typename DestinationType, typename SourceType>
246 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
247     JumpType from, SpeculativeJIT* jit, SourceType source, DestinationType destination)
248 {
249     SourceType sourceArray[1] = { source };
250     DestinationType destinationArray[1] = { destination };
251     return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 1>>(
252         from, jit, destinationArray, sourceArray);
253 }
254
255 template<typename JumpType, typename DestinationType, typename SourceType>
256 inline std::unique_ptr<SlowPathGenerator> slowPathMove(
257     JumpType from, SpeculativeJIT* jit, SourceType source1, DestinationType destination1, SourceType source2, DestinationType destination2)
258 {
259     SourceType sourceArray[2] = { source1, source2 };
260     DestinationType destinationArray[2] = { destination1, destination2 };
261     return std::make_unique<AssigningSlowPathGenerator<JumpType, DestinationType, SourceType, 2>>(
262         from, jit, destinationArray, sourceArray);
263 }
264
265 } } // namespace JSC::DFG
266
267 #endif // ENABLD(DFG_JIT)