355d98e79e271e9d2353dc12aba92cc77620b185
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedFunctionExecutable.h
1 /*
2  * Copyright (C) 2012-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 "CodeSpecializationKind.h"
29 #include "ConstructAbility.h"
30 #include "ConstructorKind.h"
31 #include "ExecutableInfo.h"
32 #include "ExpressionRangeInfo.h"
33 #include "Identifier.h"
34 #include "Intrinsic.h"
35 #include "JSCast.h"
36 #include "ParserModes.h"
37 #include "RegExp.h"
38 #include "SourceCode.h"
39 #include "VariableEnvironment.h"
40 #include <wtf/Optional.h>
41
42 namespace JSC {
43
44 class Decoder;
45 class FunctionMetadataNode;
46 class FunctionExecutable;
47 class ParserError;
48 class SourceProvider;
49 class UnlinkedFunctionCodeBlock;
50 class CachedFunctionExecutable;
51
52 enum UnlinkedFunctionKind {
53     UnlinkedNormalFunction,
54     UnlinkedBuiltinFunction,
55 };
56
57 class UnlinkedFunctionExecutable final : public JSCell {
58 public:
59     friend class CodeCache;
60     friend class VM;
61     friend class CachedFunctionExecutable;
62
63     typedef JSCell Base;
64     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
65
66     template<typename CellType, SubspaceAccess>
67     static IsoSubspace* subspaceFor(VM& vm)
68     {
69         return &vm.unlinkedFunctionExecutableSpace.space;
70     }
71
72     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)
73     {
74         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm.heap))
75             UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, isBuiltinDefaultClassConstructor);
76         instance->finishCreation(vm);
77         return instance;
78     }
79
80     ~UnlinkedFunctionExecutable();
81
82     const Identifier& name() const { return m_name; }
83     const Identifier& ecmaName() const { return m_ecmaName; }
84     void setEcmaName(const Identifier& name) { m_ecmaName = name; }
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(
119         VM&, const SourceCode&, CodeSpecializationKind, OptionSet<CodeGenerationMode>,
120         ParserError&, SourceParseMode);
121
122     static UnlinkedFunctionExecutable* fromGlobalCode(
123         const Identifier&, ExecState&, const SourceCode&, JSObject*& exception, 
124         int overrideLineNumber, Optional<int> functionConstructorParametersEndPosition);
125
126     SourceCode linkedSourceCode(const SourceCode&) const;
127     JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, ScriptExecutable* topLevelExecutable, const SourceCode& parentSource, Optional<int> overrideLineNumber = WTF::nullopt, Intrinsic = NoIntrinsic);
128
129     void clearCode(VM& vm)
130     {
131         m_unlinkedCodeBlockForCall.clear();
132         m_unlinkedCodeBlockForConstruct.clear();
133         vm.unlinkedFunctionExecutableSpace.set.remove(this);
134     }
135
136     void recordParse(CodeFeatures features, bool hasCapturedVariables)
137     {
138         m_features = features;
139         m_hasCapturedVariables = hasCapturedVariables;
140     }
141
142     CodeFeatures features() const { return m_features; }
143     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
144
145     static const bool needsDestruction = true;
146     static void destroy(JSCell*);
147
148     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
149     bool isAnonymousBuiltinFunction() const { return isBuiltinFunction() && name().isPrivateName(); }
150     ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); }
151     JSParserScriptMode scriptMode() const { return static_cast<JSParserScriptMode>(m_scriptMode); }
152     bool isClassConstructorFunction() const
153     {
154         switch (constructorKind()) {
155         case ConstructorKind::None:
156         case ConstructorKind::Naked:
157             return false;
158         case ConstructorKind::Base:
159         case ConstructorKind::Extends:
160             return true;
161         }
162         return false;
163     }
164     bool isClass() const
165     {
166         if (!m_rareData)
167             return false;
168         return !m_rareData->m_classSource.isNull();
169     }
170
171     VariableEnvironment parentScopeTDZVariables() const
172     {
173         if (!m_rareData || !m_rareData->m_parentScopeTDZVariables)
174             return VariableEnvironment();
175         return m_rareData->m_parentScopeTDZVariables.environment().toVariableEnvironment();
176     }
177     
178     bool isArrowFunction() const { return isArrowFunctionParseMode(parseMode()); }
179
180     JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
181
182     String sourceURLDirective() const
183     {
184         if (m_rareData)
185             return m_rareData->m_sourceURLDirective;
186         return String();
187     }
188     String sourceMappingURLDirective() const
189     {
190         if (m_rareData)
191             return m_rareData->m_sourceMappingURLDirective;
192         return String();
193     }
194     void setSourceURLDirective(const String& sourceURL)
195     {
196         ensureRareData().m_sourceURLDirective = sourceURL;
197     }
198     void setSourceMappingURLDirective(const String& sourceMappingURL)
199     {
200         ensureRareData().m_sourceMappingURLDirective = sourceMappingURL;
201     }
202
203     void finalizeUnconditionally(VM&);
204
205     struct RareData {
206         WTF_MAKE_STRUCT_FAST_ALLOCATED;
207
208         SourceCode m_classSource;
209         String m_sourceURLDirective;
210         String m_sourceMappingURLDirective;
211         CompactVariableMap::Handle m_parentScopeTDZVariables;
212     };
213
214 private:
215     UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>,  JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
216     UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&);
217
218     void decodeCachedCodeBlocks(VM&);
219
220     bool codeBlockEdgeMayBeWeak() const
221     {
222         // Currently, bytecode cache assumes that the tree of UnlinkedFunctionExecutable and UnlinkedCodeBlock will not be destroyed while the parent is live.
223         // Bytecode cache uses this asumption to avoid duplicate materialization by bookkeeping the heap cells in the offste-to-pointer map.
224         return VM::useUnlinkedCodeBlockJettisoning() && !m_isGeneratedFromCache;
225     }
226
227     unsigned m_firstLineOffset : 31;
228     unsigned m_isInStrictContext : 1;
229     unsigned m_lineCount : 31;
230     unsigned m_hasCapturedVariables : 1;
231     unsigned m_unlinkedFunctionNameStart : 31;
232     unsigned m_isBuiltinFunction : 1;
233     unsigned m_unlinkedBodyStartColumn : 31;
234     unsigned m_isBuiltinDefaultClassConstructor : 1;
235     unsigned m_unlinkedBodyEndColumn : 31;
236     unsigned m_constructAbility: 1;
237     unsigned m_startOffset : 31;
238     unsigned m_scriptMode: 1; // JSParserScriptMode
239     unsigned m_sourceLength : 31;
240     unsigned m_superBinding : 1;
241     unsigned m_parametersStartOffset : 31;
242     unsigned m_isCached : 1;
243     unsigned m_typeProfilingStartOffset;
244     unsigned m_typeProfilingEndOffset;
245     unsigned m_parameterCount;
246     CodeFeatures m_features;
247     SourceParseMode m_sourceParseMode;
248     unsigned m_constructorKind : 2;
249     unsigned m_functionMode : 2; // FunctionMode
250     unsigned m_derivedContextType: 2;
251     unsigned m_isGeneratedFromCache : 1;
252
253     union {
254         WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
255         RefPtr<Decoder> m_decoder;
256     };
257
258     union {
259         WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
260         struct {
261             int32_t m_cachedCodeBlockForCallOffset;
262             int32_t m_cachedCodeBlockForConstructOffset;
263         };
264     };
265
266     Identifier m_name;
267     Identifier m_ecmaName;
268
269     RareData& ensureRareData()
270     {
271         if (LIKELY(m_rareData))
272             return *m_rareData;
273         return ensureRareDataSlow();
274     }
275     RareData& ensureRareDataSlow();
276
277     std::unique_ptr<RareData> m_rareData;
278
279 protected:
280     static void visitChildren(JSCell*, SlotVisitor&);
281
282 public:
283     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
284     {
285         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
286     }
287
288     DECLARE_EXPORT_INFO;
289 };
290
291 } // namespace JSC