We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSFunction.h
1 /*
2  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003-2018 Apple Inc. All rights reserved.
4  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
5  *  Copyright (C) 2007 Maks Orlovich
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #pragma once
25
26 #include "FunctionRareData.h"
27 #include "InternalFunction.h"
28 #include "JSCallee.h"
29 #include "JSScope.h"
30
31 namespace JSC {
32
33 class ExecutableBase;
34 class FunctionExecutable;
35 class FunctionPrototype;
36 class JSLexicalEnvironment;
37 class JSGlobalObject;
38 class LLIntOffsetsExtractor;
39 class NativeExecutable;
40 class SourceCode;
41 class InternalFunction;
42 namespace DFG {
43 class SpeculativeJIT;
44 class JITCompiler;
45 }
46
47 namespace DOMJIT {
48 class Signature;
49 }
50
51
52 JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
53
54 JS_EXPORT_PRIVATE String getCalculatedDisplayName(VM&, JSObject*);
55
56 class JSFunction : public JSCallee {
57     friend class JIT;
58     friend class DFG::SpeculativeJIT;
59     friend class DFG::JITCompiler;
60     friend class VM;
61     friend class InternalFunction;
62
63 public:
64     
65     template<typename CellType>
66     static IsoSubspace* subspaceFor(VM& vm)
67     {
68         return &vm.functionSpace;
69     }
70     
71     typedef JSCallee Base;
72     const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | OverridesGetCallData;
73
74     static size_t allocationSize(Checked<size_t> inlineCapacity)
75     {
76         ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
77         return sizeof(JSFunction);
78     }
79
80     static Structure* selectStructureForNewFuncExp(JSGlobalObject*, FunctionExecutable*);
81
82     JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor, const DOMJIT::Signature* = nullptr);
83     
84     static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*);
85
86     JS_EXPORT_PRIVATE static JSFunction* create(VM&, FunctionExecutable*, JSScope*);
87     static JSFunction* create(VM&, FunctionExecutable*, JSScope*, Structure*);
88
89     JS_EXPORT_PRIVATE String name(VM&);
90     JS_EXPORT_PRIVATE String displayName(VM&);
91     const String calculatedDisplayName(VM&);
92
93     ExecutableBase* executable() const { return m_executable.get(); }
94
95     // To call any of these methods include JSFunctionInlines.h
96     bool isHostFunction() const;
97     FunctionExecutable* jsExecutable() const;
98     Intrinsic intrinsic() const;
99
100     JS_EXPORT_PRIVATE const SourceCode* sourceCode() const;
101
102     DECLARE_EXPORT_INFO;
103
104     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 
105     {
106         ASSERT(globalObject);
107         return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); 
108     }
109
110     TaggedNativeFunction nativeFunction();
111     TaggedNativeFunction nativeConstructor();
112
113     static ConstructType getConstructData(JSCell*, ConstructData&);
114     static CallType getCallData(JSCell*, CallData&);
115
116     static inline ptrdiff_t offsetOfExecutable()
117     {
118         return OBJECT_OFFSETOF(JSFunction, m_executable);
119     }
120
121     static inline ptrdiff_t offsetOfRareData()
122     {
123         return OBJECT_OFFSETOF(JSFunction, m_rareData);
124     }
125
126     FunctionRareData* rareData(VM& vm)
127     {
128         if (UNLIKELY(!m_rareData))
129             return allocateRareData(vm);
130         return m_rareData.get();
131     }
132
133     FunctionRareData* ensureRareDataAndAllocationProfile(ExecState*, unsigned inlineCapacity);
134
135     FunctionRareData* rareData()
136     {
137         FunctionRareData* rareData = m_rareData.get();
138
139         // The JS thread may be concurrently creating the rare data
140         // If we see it, we want to ensure it has been properly created
141         WTF::loadLoadFence();
142
143         return rareData;
144     }
145
146     bool isHostOrBuiltinFunction() const;
147     bool isBuiltinFunction() const;
148     JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
149     bool isClassConstructorFunction() const;
150
151     void setFunctionName(ExecState*, JSValue name);
152
153     // Returns the __proto__ for the |this| value if this JSFunction were to be constructed.
154     JSObject* prototypeForConstruction(VM&, ExecState*);
155
156     bool canUseAllocationProfile();
157     bool canUseAllocationProfileNonInline();
158
159     enum class PropertyStatus {
160         Eager,
161         Lazy,
162         Reified,
163     };
164     PropertyStatus reifyLazyPropertyIfNeeded(VM&, ExecState*, PropertyName);
165
166 protected:
167     JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
168     JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
169
170     void finishCreation(VM&, NativeExecutable*, int length, const String& name);
171     void finishCreation(VM&);
172
173     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
174     static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = EnumerationMode());
175     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
176
177     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
178
179     static bool deleteProperty(JSCell*, ExecState*, PropertyName);
180
181     static void visitChildren(JSCell*, SlotVisitor&);
182
183 private:
184     static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
185     {
186         JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope, structure);
187         ASSERT(function->structure(vm)->globalObject());
188         function->finishCreation(vm);
189         return function;
190     }
191
192     FunctionRareData* allocateRareData(VM&);
193     FunctionRareData* allocateAndInitializeRareData(ExecState*, size_t inlineCapacity);
194     FunctionRareData* initializeRareData(ExecState*, size_t inlineCapacity);
195
196     bool hasReifiedLength() const;
197     bool hasReifiedName() const;
198     void reifyLength(VM&);
199     void reifyName(VM&, ExecState*);
200     void reifyName(VM&, ExecState*, String name);
201
202     static bool isLazy(PropertyStatus property) { return property == PropertyStatus::Lazy || property == PropertyStatus::Reified; }
203     static bool isReified(PropertyStatus property) { return property == PropertyStatus::Reified; }
204
205     PropertyStatus reifyLazyPropertyForHostOrBuiltinIfNeeded(VM&, ExecState*, PropertyName);
206     PropertyStatus reifyLazyLengthIfNeeded(VM&, ExecState*, PropertyName);
207     PropertyStatus reifyLazyNameIfNeeded(VM&, ExecState*, PropertyName);
208     PropertyStatus reifyLazyBoundNameIfNeeded(VM&, ExecState*, PropertyName);
209
210 #if ASSERT_DISABLED
211     void assertTypeInfoFlagInvariants() { }
212 #else
213     void assertTypeInfoFlagInvariants();
214 #endif
215
216     friend class LLIntOffsetsExtractor;
217
218     static EncodedJSValue argumentsGetter(ExecState*, EncodedJSValue, PropertyName);
219     static EncodedJSValue callerGetter(ExecState*, EncodedJSValue, PropertyName);
220     static EncodedJSValue lengthGetter(ExecState*, EncodedJSValue, PropertyName);
221     static EncodedJSValue nameGetter(ExecState*, EncodedJSValue, PropertyName);
222
223     template<typename T>
224     using PoisonedBarrier = PoisonedWriteBarrier<JSFunctionPoison, T>;
225     
226     PoisonedBarrier<ExecutableBase> m_executable;
227     PoisonedBarrier<FunctionRareData> m_rareData;
228 };
229
230 } // namespace JSC