1/*
2 * Copyright (C) 2009-2019 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 "CallData.h"
30#include "CodeBlockHash.h"
31#include "CodeSpecializationKind.h"
32#include "JITCode.h"
33#include "JSGlobalObject.h"
34#include "UnlinkedCodeBlock.h"
35#include "UnlinkedFunctionExecutable.h"
36
37namespace JSC {
38
39class CodeBlock;
40class EvalCodeBlock;
41class FunctionCodeBlock;
42class JSScope;
43class JSWebAssemblyModule;
44class LLIntOffsetsExtractor;
45class ModuleProgramCodeBlock;
46class ProgramCodeBlock;
47
48enum CompilationKind { FirstCompilation, OptimizingCompilation };
49
50inline bool isCall(CodeSpecializationKind kind)
51{
52 if (kind == CodeForCall)
53 return true;
54 ASSERT(kind == CodeForConstruct);
55 return false;
56}
57
58class ExecutableBase : public JSCell {
59 friend class JIT;
60 friend MacroAssemblerCodeRef<JITThunkPtrTag> boundThisNoArgsFunctionCallGenerator(VM*);
61
62protected:
63 ExecutableBase(VM& vm, Structure* structure)
64 : JSCell(vm, structure)
65 {
66 }
67
68 void finishCreation(VM& vm)
69 {
70 Base::finishCreation(vm);
71 }
72
73public:
74 typedef JSCell Base;
75 static constexpr unsigned StructureFlags = Base::StructureFlags;
76
77 static constexpr bool needsDestruction = true;
78 static void destroy(JSCell*);
79
80 // Force subclasses to override this.
81 template<typename, SubspaceAccess>
82 static void subspaceFor(VM&) { }
83
84 CodeBlockHash hashFor(CodeSpecializationKind) const;
85
86 bool isEvalExecutable() const
87 {
88 return type() == EvalExecutableType;
89 }
90 bool isFunctionExecutable() const
91 {
92 return type() == FunctionExecutableType;
93 }
94 bool isProgramExecutable() const
95 {
96 return type() == ProgramExecutableType;
97 }
98 bool isModuleProgramExecutable()
99 {
100 return type() == ModuleProgramExecutableType;
101 }
102 bool isHostFunction() const
103 {
104 return type() == NativeExecutableType;
105 }
106
107 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); }
108
109 DECLARE_EXPORT_INFO;
110
111public:
112 Ref<JITCode> generatedJITCodeForCall() const
113 {
114 ASSERT(m_jitCodeForCall);
115 return *m_jitCodeForCall;
116 }
117
118 Ref<JITCode> generatedJITCodeForConstruct() const
119 {
120 ASSERT(m_jitCodeForConstruct);
121 return *m_jitCodeForConstruct;
122 }
123
124 Ref<JITCode> generatedJITCodeFor(CodeSpecializationKind kind) const
125 {
126 if (kind == CodeForCall)
127 return generatedJITCodeForCall();
128 ASSERT(kind == CodeForConstruct);
129 return generatedJITCodeForConstruct();
130 }
131
132 MacroAssemblerCodePtr<JSEntryPtrTag> entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity)
133 {
134 // Check if we have a cached result. We only have it for arity check because we use the
135 // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in
136 // machine code.
137 if (arity == MustCheckArity) {
138 switch (kind) {
139 case CodeForCall:
140 if (MacroAssemblerCodePtr<JSEntryPtrTag> result = m_jitCodeForCallWithArityCheck)
141 return result;
142 break;
143 case CodeForConstruct:
144 if (MacroAssemblerCodePtr<JSEntryPtrTag> result = m_jitCodeForConstructWithArityCheck)
145 return result;
146 break;
147 }
148 }
149 MacroAssemblerCodePtr<JSEntryPtrTag> result = generatedJITCodeFor(kind)->addressForCall(arity);
150 if (arity == MustCheckArity) {
151 // Cache the result; this is necessary for the JIT's virtual call optimizations.
152 switch (kind) {
153 case CodeForCall:
154 m_jitCodeForCallWithArityCheck = result;
155 break;
156 case CodeForConstruct:
157 m_jitCodeForConstructWithArityCheck = result;
158 break;
159 }
160 }
161 return result;
162 }
163
164 static ptrdiff_t offsetOfJITCodeWithArityCheckFor(
165 CodeSpecializationKind kind)
166 {
167 switch (kind) {
168 case CodeForCall:
169 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck);
170 case CodeForConstruct:
171 return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck);
172 }
173 RELEASE_ASSERT_NOT_REACHED();
174 return 0;
175 }
176
177 bool hasJITCodeForCall() const;
178 bool hasJITCodeForConstruct() const;
179
180 bool hasJITCodeFor(CodeSpecializationKind kind) const
181 {
182 if (kind == CodeForCall)
183 return hasJITCodeForCall();
184 ASSERT(kind == CodeForConstruct);
185 return hasJITCodeForConstruct();
186 }
187
188 // Intrinsics are only for calls, currently.
189 Intrinsic intrinsic() const;
190
191 Intrinsic intrinsicFor(CodeSpecializationKind kind) const
192 {
193 if (isCall(kind))
194 return intrinsic();
195 return NoIntrinsic;
196 }
197
198 void dump(PrintStream&) const;
199
200protected:
201 RefPtr<JITCode> m_jitCodeForCall;
202 RefPtr<JITCode> m_jitCodeForConstruct;
203 MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForCallWithArityCheck;
204 MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForConstructWithArityCheck;
205};
206
207} // namespace JSC
208