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