742fd21ceb8a0638dcc3836ee7997e2a3f0f6e40
[WebKit-https.git] / Source / JavaScriptCore / jit / JITCode.h
1 /*
2  * Copyright (C) 2008-2018 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 #include "ArityCheckMode.h"
29 #include "CallFrame.h"
30 #include "CodeOrigin.h"
31 #include "JSCJSValue.h"
32 #include "MacroAssemblerCodeRef.h"
33 #include "RegisterSet.h"
34 #include <wtf/Optional.h>
35
36 namespace JSC {
37
38 namespace DFG {
39 class CommonData;
40 class JITCode;
41 }
42 namespace FTL {
43 class ForOSREntryJITCode;
44 class JITCode;
45 }
46 namespace DOMJIT {
47 class Signature;
48 }
49
50 struct ProtoCallFrame;
51 class TrackedReferences;
52 class VM;
53
54 class JITCode : public ThreadSafeRefCounted<JITCode> {
55 public:
56     template<PtrTag tag> using CodePtr = MacroAssemblerCodePtr<tag>;
57     template<PtrTag tag> using CodeRef = MacroAssemblerCodeRef<tag>;
58
59     enum JITType : uint8_t {
60         None,
61         HostCallThunk,
62         InterpreterThunk,
63         BaselineJIT,
64         DFGJIT,
65         FTLJIT
66     };
67     
68     static const char* typeName(JITType);
69
70     static JITType bottomTierJIT()
71     {
72         return BaselineJIT;
73     }
74     
75     static JITType topTierJIT()
76     {
77         return FTLJIT;
78     }
79     
80     static JITType nextTierJIT(JITType jitType)
81     {
82         switch (jitType) {
83         case BaselineJIT:
84             return DFGJIT;
85         case DFGJIT:
86             return FTLJIT;
87         default:
88             RELEASE_ASSERT_NOT_REACHED();
89             return None;
90         }
91     }
92     
93     static bool isExecutableScript(JITType jitType)
94     {
95         switch (jitType) {
96         case None:
97         case HostCallThunk:
98             return false;
99         default:
100             return true;
101         }
102     }
103     
104     static bool couldBeInterpreted(JITType jitType)
105     {
106         switch (jitType) {
107         case InterpreterThunk:
108         case BaselineJIT:
109             return true;
110         default:
111             return false;
112         }
113     }
114     
115     static bool isJIT(JITType jitType)
116     {
117         switch (jitType) {
118         case BaselineJIT:
119         case DFGJIT:
120         case FTLJIT:
121             return true;
122         default:
123             return false;
124         }
125     }
126
127     static bool isLowerTier(JITType expectedLower, JITType expectedHigher)
128     {
129         RELEASE_ASSERT(isExecutableScript(expectedLower));
130         RELEASE_ASSERT(isExecutableScript(expectedHigher));
131         return expectedLower < expectedHigher;
132     }
133     
134     static bool isHigherTier(JITType expectedHigher, JITType expectedLower)
135     {
136         return isLowerTier(expectedLower, expectedHigher);
137     }
138     
139     static bool isLowerOrSameTier(JITType expectedLower, JITType expectedHigher)
140     {
141         return !isHigherTier(expectedLower, expectedHigher);
142     }
143     
144     static bool isHigherOrSameTier(JITType expectedHigher, JITType expectedLower)
145     {
146         return isLowerOrSameTier(expectedLower, expectedHigher);
147     }
148     
149     static bool isOptimizingJIT(JITType jitType)
150     {
151         return jitType == DFGJIT || jitType == FTLJIT;
152     }
153     
154     static bool isBaselineCode(JITType jitType)
155     {
156         return jitType == InterpreterThunk || jitType == BaselineJIT;
157     }
158
159     virtual const DOMJIT::Signature* signature() const { return nullptr; }
160     
161     enum class ShareAttribute : uint8_t {
162         NotShared,
163         Shared
164     };
165
166 protected:
167     JITCode(JITType, JITCode::ShareAttribute = JITCode::ShareAttribute::NotShared);
168     
169 public:
170     virtual ~JITCode();
171     
172     JITType jitType() const
173     {
174         return m_jitType;
175     }
176     
177     template<typename PointerType>
178     static JITType jitTypeFor(PointerType jitCode)
179     {
180         if (!jitCode)
181             return None;
182         return jitCode->jitType();
183     }
184     
185     virtual CodePtr<JSEntryPtrTag> addressForCall(ArityCheckMode) = 0;
186     virtual void* executableAddressAtOffset(size_t offset) = 0;
187     void* executableAddress() { return executableAddressAtOffset(0); }
188     virtual void* dataAddressAtOffset(size_t offset) = 0;
189     virtual unsigned offsetOf(void* pointerIntoCode) = 0;
190     
191     virtual DFG::CommonData* dfgCommon();
192     virtual DFG::JITCode* dfg();
193     virtual FTL::JITCode* ftl();
194     virtual FTL::ForOSREntryJITCode* ftlForOSREntry();
195     
196     virtual void validateReferences(const TrackedReferences&);
197     
198     JSValue execute(VM*, ProtoCallFrame*);
199     
200     void* start() { return dataAddressAtOffset(0); }
201     virtual size_t size() = 0;
202     void* end() { return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start()) + size()); }
203     
204     virtual bool contains(void*) = 0;
205
206 #if ENABLE(JIT)
207     virtual RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex);
208     virtual Optional<CodeOrigin> findPC(CodeBlock*, void* pc) { UNUSED_PARAM(pc); return WTF::nullopt; }
209 #endif
210
211     Intrinsic intrinsic() { return m_intrinsic; }
212
213     bool isShared() const { return m_shareAttribute == ShareAttribute::Shared; }
214
215 private:
216     JITType m_jitType;
217     ShareAttribute m_shareAttribute;
218 protected:
219     Intrinsic m_intrinsic { NoIntrinsic }; // Effective only in NativeExecutable.
220 };
221
222 class JITCodeWithCodeRef : public JITCode {
223 protected:
224     JITCodeWithCodeRef(JITType);
225     JITCodeWithCodeRef(CodeRef<JSEntryPtrTag>, JITType, JITCode::ShareAttribute);
226
227 public:
228     virtual ~JITCodeWithCodeRef();
229
230     void* executableAddressAtOffset(size_t offset) override;
231     void* dataAddressAtOffset(size_t offset) override;
232     unsigned offsetOf(void* pointerIntoCode) override;
233     size_t size() override;
234     bool contains(void*) override;
235
236 protected:
237     CodeRef<JSEntryPtrTag> m_ref;
238 };
239
240 class DirectJITCode : public JITCodeWithCodeRef {
241 public:
242     DirectJITCode(JITType);
243     DirectJITCode(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck, JITType, JITCode::ShareAttribute = JITCode::ShareAttribute::NotShared);
244     DirectJITCode(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck, JITType, Intrinsic, JITCode::ShareAttribute = JITCode::ShareAttribute::NotShared); // For generated thunk.
245     virtual ~DirectJITCode();
246     
247     CodePtr<JSEntryPtrTag> addressForCall(ArityCheckMode) override;
248
249 protected:
250     void initializeCodeRefForDFG(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck);
251
252 private:
253     CodePtr<JSEntryPtrTag> m_withArityCheck;
254 };
255
256 class NativeJITCode : public JITCodeWithCodeRef {
257 public:
258     NativeJITCode(JITType);
259     NativeJITCode(CodeRef<JSEntryPtrTag>, JITType, Intrinsic, JITCode::ShareAttribute = JITCode::ShareAttribute::NotShared);
260     virtual ~NativeJITCode();
261
262     CodePtr<JSEntryPtrTag> addressForCall(ArityCheckMode) override;
263 };
264
265 class NativeDOMJITCode final : public NativeJITCode {
266 public:
267     NativeDOMJITCode(CodeRef<JSEntryPtrTag>, JITType, Intrinsic, const DOMJIT::Signature*);
268     virtual ~NativeDOMJITCode() = default;
269
270     const DOMJIT::Signature* signature() const override { return m_signature; }
271
272 private:
273     const DOMJIT::Signature* m_signature;
274 };
275
276 } // namespace JSC
277
278 namespace WTF {
279
280 class PrintStream;
281 void printInternal(PrintStream&, JSC::JITCode::JITType);
282
283 } // namespace WTF