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
36namespace JSC {
37
38namespace DFG {
39class CommonData;
40class JITCode;
41}
42namespace FTL {
43class ForOSREntryJITCode;
44class JITCode;
45}
46namespace DOMJIT {
47class Signature;
48}
49
50struct ProtoCallFrame;
51class TrackedReferences;
52class VM;
53
54enum class JITType : uint8_t {
55 None,
56 HostCallThunk,
57 InterpreterThunk,
58 BaselineJIT,
59 DFGJIT,
60 FTLJIT
61};
62
63class JITCode : public ThreadSafeRefCounted<JITCode> {
64public:
65 template<PtrTag tag> using CodePtr = MacroAssemblerCodePtr<tag>;
66 template<PtrTag tag> using CodeRef = MacroAssemblerCodeRef<tag>;
67
68 static const char* typeName(JITType);
69
70 static JITType bottomTierJIT()
71 {
72 return JITType::BaselineJIT;
73 }
74
75 static JITType topTierJIT()
76 {
77 return JITType::FTLJIT;
78 }
79
80 static JITType nextTierJIT(JITType jitType)
81 {
82 switch (jitType) {
83 case JITType::BaselineJIT:
84 return JITType::DFGJIT;
85 case JITType::DFGJIT:
86 return JITType::FTLJIT;
87 default:
88 RELEASE_ASSERT_NOT_REACHED();
89 return JITType::None;
90 }
91 }
92
93 static bool isExecutableScript(JITType jitType)
94 {
95 switch (jitType) {
96 case JITType::None:
97 case JITType::HostCallThunk:
98 return false;
99 default:
100 return true;
101 }
102 }
103
104 static bool couldBeInterpreted(JITType jitType)
105 {
106 switch (jitType) {
107 case JITType::InterpreterThunk:
108 case JITType::BaselineJIT:
109 return true;
110 default:
111 return false;
112 }
113 }
114
115 static bool isJIT(JITType jitType)
116 {
117 switch (jitType) {
118 case JITType::BaselineJIT:
119 case JITType::DFGJIT:
120 case JITType::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 == JITType::DFGJIT || jitType == JITType::FTLJIT;
152 }
153
154 static bool isBaselineCode(JITType jitType)
155 {
156 return jitType == JITType::InterpreterThunk || jitType == 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
166protected:
167 JITCode(JITType, JITCode::ShareAttribute = JITCode::ShareAttribute::NotShared);
168
169public:
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 JITType::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
215private:
216 JITType m_jitType;
217 ShareAttribute m_shareAttribute;
218protected:
219 Intrinsic m_intrinsic { NoIntrinsic }; // Effective only in NativeExecutable.
220};
221
222class JITCodeWithCodeRef : public JITCode {
223protected:
224 JITCodeWithCodeRef(JITType);
225 JITCodeWithCodeRef(CodeRef<JSEntryPtrTag>, JITType, JITCode::ShareAttribute);
226
227public:
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
236protected:
237 CodeRef<JSEntryPtrTag> m_ref;
238};
239
240class DirectJITCode : public JITCodeWithCodeRef {
241public:
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
249protected:
250 void initializeCodeRefForDFG(CodeRef<JSEntryPtrTag>, CodePtr<JSEntryPtrTag> withArityCheck);
251
252private:
253 CodePtr<JSEntryPtrTag> m_withArityCheck;
254};
255
256class NativeJITCode : public JITCodeWithCodeRef {
257public:
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
265class NativeDOMJITCode final : public NativeJITCode {
266public:
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
272private:
273 const DOMJIT::Signature* m_signature;
274};
275
276} // namespace JSC
277
278namespace WTF {
279
280class PrintStream;
281void printInternal(PrintStream&, JSC::JITType);
282
283} // namespace WTF
284