1/*
2 * Copyright (C) 2012-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 "CodeSpecializationKind.h"
29#include "ConstructAbility.h"
30#include "ExecutableInfo.h"
31#include "ExpressionRangeInfo.h"
32#include "Identifier.h"
33#include "Intrinsic.h"
34#include "JSCast.h"
35#include "ParserModes.h"
36#include "RegExp.h"
37#include "SourceCode.h"
38#include "VariableEnvironment.h"
39#include <wtf/Optional.h>
40
41namespace JSC {
42
43class Decoder;
44class FunctionMetadataNode;
45class FunctionExecutable;
46class ParserError;
47class SourceProvider;
48class UnlinkedFunctionCodeBlock;
49class CachedFunctionExecutable;
50
51enum UnlinkedFunctionKind {
52 UnlinkedNormalFunction,
53 UnlinkedBuiltinFunction,
54};
55
56class UnlinkedFunctionExecutable final : public JSCell {
57public:
58 friend class CodeCache;
59 friend class VM;
60 friend class CachedFunctionExecutable;
61
62 typedef JSCell Base;
63 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
64
65 template<typename CellType, SubspaceAccess>
66 static IsoSubspace* subspaceFor(VM& vm)
67 {
68 return &vm.unlinkedFunctionExecutableSpace.space;
69 }
70
71 static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false)
72 {
73 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
74 UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, isBuiltinDefaultClassConstructor);
75 instance->finishCreation(*vm);
76 return instance;
77 }
78
79 ~UnlinkedFunctionExecutable();
80
81 const Identifier& name() const { return m_name; }
82 const Identifier& ecmaName() const { return m_ecmaName; }
83 void setEcmaName(const Identifier& name) { m_ecmaName = name; }
84 const Identifier& inferredName() const { return m_inferredName; }
85 unsigned parameterCount() const { return m_parameterCount; }; // Excluding 'this'!
86 SourceParseMode parseMode() const { return static_cast<SourceParseMode>(m_sourceParseMode); };
87
88 SourceCode classSource() const
89 {
90 if (m_rareData)
91 return m_rareData->m_classSource;
92 return SourceCode();
93 }
94 void setClassSource(const SourceCode& source)
95 {
96 ensureRareData().m_classSource = source;
97 }
98
99 bool isInStrictContext() const { return m_isInStrictContext; }
100 FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
101 ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
102 SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
103
104 unsigned lineCount() const { return m_lineCount; }
105 unsigned linkedStartColumn(unsigned parentStartColumn) const { return m_unlinkedBodyStartColumn + (!m_firstLineOffset ? parentStartColumn : 1); }
106 unsigned linkedEndColumn(unsigned startColumn) const { return m_unlinkedBodyEndColumn + (!m_lineCount ? startColumn : 1); }
107
108 unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
109 unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
110 unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
111 unsigned startOffset() const { return m_startOffset; }
112 unsigned sourceLength() { return m_sourceLength; }
113 unsigned parametersStartOffset() const { return m_parametersStartOffset; }
114 unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
115 unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
116 void setInvalidTypeProfilingOffsets();
117
118 UnlinkedFunctionCodeBlock* unlinkedCodeBlockFor(CodeSpecializationKind);
119
120 UnlinkedFunctionCodeBlock* unlinkedCodeBlockFor(
121 VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode,
122 ParserError&, SourceParseMode);
123
124 static UnlinkedFunctionExecutable* fromGlobalCode(
125 const Identifier&, ExecState&, const SourceCode&, JSObject*& exception,
126 int overrideLineNumber, Optional<int> functionConstructorParametersEndPosition);
127
128 SourceCode linkedSourceCode(const SourceCode&) const;
129 JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode& parentSource, Optional<int> overrideLineNumber = WTF::nullopt, Intrinsic = NoIntrinsic);
130
131 void clearCode(VM& vm)
132 {
133 m_unlinkedCodeBlockForCall.clear();
134 m_unlinkedCodeBlockForConstruct.clear();
135 vm.unlinkedFunctionExecutableSpace.set.remove(this);
136 }
137
138 void recordParse(CodeFeatures features, bool hasCapturedVariables)
139 {
140 m_features = features;
141 m_hasCapturedVariables = hasCapturedVariables;
142 }
143
144 CodeFeatures features() const { return m_features; }
145 bool hasCapturedVariables() const { return m_hasCapturedVariables; }
146
147 static const bool needsDestruction = true;
148 static void destroy(JSCell*);
149
150 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
151 ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); }
152 JSParserScriptMode scriptMode() const { return static_cast<JSParserScriptMode>(m_scriptMode); }
153 bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; }
154 bool isClass() const
155 {
156 if (!m_rareData)
157 return false;
158 return !m_rareData->m_classSource.isNull();
159 }
160
161 VariableEnvironment parentScopeTDZVariables() const
162 {
163 if (!m_rareData || !m_rareData->m_parentScopeTDZVariables)
164 return VariableEnvironment();
165 return m_rareData->m_parentScopeTDZVariables.environment().toVariableEnvironment();
166 }
167
168 bool isArrowFunction() const { return isArrowFunctionParseMode(parseMode()); }
169
170 JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
171
172 String sourceURLDirective() const
173 {
174 if (m_rareData)
175 return m_rareData->m_sourceURLDirective;
176 return String();
177 }
178 String sourceMappingURLDirective() const
179 {
180 if (m_rareData)
181 return m_rareData->m_sourceMappingURLDirective;
182 return String();
183 }
184 void setSourceURLDirective(const String& sourceURL)
185 {
186 ensureRareData().m_sourceURLDirective = sourceURL;
187 }
188 void setSourceMappingURLDirective(const String& sourceMappingURL)
189 {
190 ensureRareData().m_sourceMappingURLDirective = sourceMappingURL;
191 }
192
193 struct RareData {
194 WTF_MAKE_STRUCT_FAST_ALLOCATED;
195
196 SourceCode m_classSource;
197 String m_sourceURLDirective;
198 String m_sourceMappingURLDirective;
199 CompactVariableMap::Handle m_parentScopeTDZVariables;
200 };
201
202private:
203 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
204 UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&);
205
206 void decodeCachedCodeBlocks();
207
208 unsigned m_firstLineOffset;
209 unsigned m_lineCount;
210 unsigned m_unlinkedFunctionNameStart;
211 unsigned m_unlinkedBodyStartColumn;
212 unsigned m_unlinkedBodyEndColumn;
213 unsigned m_startOffset;
214 unsigned m_sourceLength;
215 unsigned m_parametersStartOffset;
216 unsigned m_typeProfilingStartOffset;
217 unsigned m_typeProfilingEndOffset;
218 unsigned m_parameterCount;
219 CodeFeatures m_features;
220 SourceParseMode m_sourceParseMode;
221 unsigned m_isInStrictContext : 1;
222 unsigned m_hasCapturedVariables : 1;
223 unsigned m_isBuiltinFunction : 1;
224 unsigned m_isBuiltinDefaultClassConstructor : 1;
225 unsigned m_constructAbility: 1;
226 unsigned m_constructorKind : 2;
227 unsigned m_functionMode : 2; // FunctionMode
228 unsigned m_scriptMode: 1; // JSParserScriptMode
229 unsigned m_superBinding : 1;
230 unsigned m_derivedContextType: 2;
231 bool m_isCached : 1;
232
233 union {
234 WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
235 RefPtr<Decoder> m_decoder;
236 };
237
238 union {
239 WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
240 struct {
241 int32_t m_cachedCodeBlockForCallOffset;
242 int32_t m_cachedCodeBlockForConstructOffset;
243 };
244 };
245
246 Identifier m_name;
247 Identifier m_ecmaName;
248 Identifier m_inferredName;
249
250 RareData& ensureRareData()
251 {
252 if (LIKELY(m_rareData))
253 return *m_rareData;
254 return ensureRareDataSlow();
255 }
256 RareData& ensureRareDataSlow();
257
258 std::unique_ptr<RareData> m_rareData;
259
260protected:
261 static void visitChildren(JSCell*, SlotVisitor&);
262
263public:
264 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
265 {
266 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
267 }
268
269 DECLARE_EXPORT_INFO;
270};
271
272} // namespace JSC
273