1/*
2 * Copyright (C) 2012-2015 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 UnlinkedFunctionExecutable_h
27#define UnlinkedFunctionExecutable_h
28
29#include "BytecodeConventions.h"
30#include "CodeSpecializationKind.h"
31#include "CodeType.h"
32#include "ConstructAbility.h"
33#include "ExecutableInfo.h"
34#include "ExpressionRangeInfo.h"
35#include "HandlerInfo.h"
36#include "Identifier.h"
37#include "JSCell.h"
38#include "JSString.h"
39#include "ParserModes.h"
40#include "RegExp.h"
41#include "SpecialPointer.h"
42#include "VariableEnvironment.h"
43#include "VirtualRegister.h"
44#include <wtf/RefCountedArray.h>
45#include <wtf/Vector.h>
46
47namespace JSC {
48
49class FunctionMetadataNode;
50class FunctionExecutable;
51class ParserError;
52class SourceCode;
53class SourceProvider;
54class UnlinkedFunctionCodeBlock;
55
56enum UnlinkedFunctionKind {
57 UnlinkedNormalFunction,
58 UnlinkedBuiltinFunction,
59};
60
61class UnlinkedFunctionExecutable final : public JSCell {
62public:
63 friend class CodeCache;
64 friend class VM;
65
66 typedef JSCell Base;
67 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
68
69 static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, RefPtr<SourceProvider>&& sourceOverride = nullptr)
70 {
71 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
72 UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTFMove(sourceOverride), node, unlinkedFunctionKind, constructAbility, parentScopeTDZVariables, derivedContextType);
73 instance->finishCreation(*vm);
74 return instance;
75 }
76
77 const Identifier& name() const { return m_name; }
78 const Identifier& inferredName() const { return m_inferredName; }
79 JSString* nameValue() const { return m_nameValue.get(); }
80 void setNameValue(VM& vm, JSString* nameValue) { m_nameValue.set(vm, this, nameValue); }
81 unsigned parameterCount() const { return m_parameterCount; };
82 SourceParseMode parseMode() const { return static_cast<SourceParseMode>(m_sourceParseMode); };
83 bool isInStrictContext() const { return m_isInStrictContext; }
84 FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
85 ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
86 SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
87
88 unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
89 unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
90 unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
91 unsigned startOffset() const { return m_startOffset; }
92 unsigned sourceLength() { return m_sourceLength; }
93 unsigned parametersStartOffset() const { return m_parametersStartOffset; }
94 unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
95 unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
96 void setInvalidTypeProfilingOffsets();
97
98 UnlinkedFunctionCodeBlock* unlinkedCodeBlockFor(
99 VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode,
100 ParserError&, SourceParseMode);
101
102 static UnlinkedFunctionExecutable* fromGlobalCode(
103 const Identifier&, ExecState&, const SourceCode&, JSObject*& exception,
104 int overrideLineNumber);
105
106 JS_EXPORT_PRIVATE FunctionExecutable* link(VM&, const SourceCode&, int overrideLineNumber = -1);
107
108 void clearCode()
109 {
110 m_unlinkedCodeBlockForCall.clear();
111 m_unlinkedCodeBlockForConstruct.clear();
112 }
113
114 void recordParse(CodeFeatures features, bool hasCapturedVariables)
115 {
116 m_features = features;
117 m_hasCapturedVariables = hasCapturedVariables;
118 }
119
120 CodeFeatures features() const { return m_features; }
121 bool hasCapturedVariables() const { return m_hasCapturedVariables; }
122
123 static const bool needsDestruction = true;
124 static void destroy(JSCell*);
125
126 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
127 ConstructAbility constructAbility() const { return static_cast<ConstructAbility>(m_constructAbility); }
128 bool isClassConstructorFunction() const { return constructorKind() != ConstructorKind::None; }
129 const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; }
130
131 bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
132
133 JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
134
135private:
136 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&, JSC::DerivedContextType);
137
138 unsigned m_firstLineOffset;
139 unsigned m_lineCount;
140 unsigned m_unlinkedFunctionNameStart;
141 unsigned m_unlinkedBodyStartColumn;
142 unsigned m_unlinkedBodyEndColumn;
143 unsigned m_startOffset;
144 unsigned m_sourceLength;
145 unsigned m_parametersStartOffset;
146 unsigned m_typeProfilingStartOffset;
147 unsigned m_typeProfilingEndOffset;
148 unsigned m_parameterCount;
149 CodeFeatures m_features;
150 unsigned m_isInStrictContext : 1;
151 unsigned m_hasCapturedVariables : 1;
152 unsigned m_isBuiltinFunction : 1;
153 unsigned m_constructAbility: 1;
154 unsigned m_constructorKind : 2;
155 unsigned m_functionMode : 1; // FunctionMode
156 unsigned m_superBinding : 1;
157 unsigned m_derivedContextType: 2;
158 unsigned m_sourceParseMode : 4; // SourceParseMode
159
160 WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
161 WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
162
163 Identifier m_name;
164 Identifier m_inferredName;
165 WriteBarrier<JSString> m_nameValue;
166 RefPtr<SourceProvider> m_sourceOverride;
167
168 VariableEnvironment m_parentScopeTDZVariables;
169
170protected:
171 void finishCreation(VM& vm)
172 {
173 Base::finishCreation(vm);
174 m_nameValue.set(vm, this, jsString(&vm, name().string()));
175 }
176
177 static void visitChildren(JSCell*, SlotVisitor&);
178
179public:
180 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
181 {
182 return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
183 }
184
185 DECLARE_EXPORT_INFO;
186};
187
188} // namespace JSC
189
190#endif // UnlinkedFunctionExecutable_h
191