1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2006-2009, 2015-2016 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#ifndef JSFunction_h
25#define JSFunction_h
26
27#include "FunctionRareData.h"
28#include "InternalFunction.h"
29#include "JSCallee.h"
30#include "JSScope.h"
31#include "Watchpoint.h"
32
33namespace JSC {
34
35class ExecutableBase;
36class FunctionExecutable;
37class FunctionPrototype;
38class JSLexicalEnvironment;
39class JSGlobalObject;
40class LLIntOffsetsExtractor;
41class NativeExecutable;
42class SourceCode;
43class WebAssemblyExecutable;
44class InternalFunction;
45namespace DFG {
46class SpeculativeJIT;
47class JITCompiler;
48}
49
50JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
51
52JS_EXPORT_PRIVATE String getCalculatedDisplayName(CallFrame*, JSObject*);
53
54class JSFunction : public JSCallee {
55 friend class JIT;
56 friend class DFG::SpeculativeJIT;
57 friend class DFG::JITCompiler;
58 friend class VM;
59 friend class InternalFunction;
60
61public:
62 typedef JSCallee Base;
63 const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
64
65 static size_t allocationSize(size_t inlineCapacity)
66 {
67 ASSERT_UNUSED(inlineCapacity, !inlineCapacity);
68 return sizeof(JSFunction);
69 }
70
71 JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
72
73 static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*);
74
75 static JSFunction* create(VM&, FunctionExecutable*, JSScope*);
76 static JSFunction* create(VM&, FunctionExecutable*, JSScope*, Structure*);
77#if ENABLE(WEBASSEMBLY)
78 static JSFunction* create(VM&, WebAssemblyExecutable*, JSScope*);
79#endif
80
81 JS_EXPORT_PRIVATE static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
82 static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name);
83
84 JS_EXPORT_PRIVATE String name(ExecState*);
85 JS_EXPORT_PRIVATE String displayName(ExecState*);
86 const String calculatedDisplayName(ExecState*);
87
88 ExecutableBase* executable() const { return m_executable.get(); }
89
90 // To call any of these methods include JSFunctionInlines.h
91 bool isHostFunction() const;
92 FunctionExecutable* jsExecutable() const;
93 Intrinsic intrinsic() const;
94
95 JS_EXPORT_PRIVATE const SourceCode* sourceCode() const;
96
97 DECLARE_EXPORT_INFO;
98
99 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
100 {
101 ASSERT(globalObject);
102 return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
103 }
104
105 NativeFunction nativeFunction();
106 NativeFunction nativeConstructor();
107
108 static ConstructType getConstructData(JSCell*, ConstructData&);
109 static CallType getCallData(JSCell*, CallData&);
110
111 static inline ptrdiff_t offsetOfExecutable()
112 {
113 return OBJECT_OFFSETOF(JSFunction, m_executable);
114 }
115
116 static inline ptrdiff_t offsetOfRareData()
117 {
118 return OBJECT_OFFSETOF(JSFunction, m_rareData);
119 }
120
121 FunctionRareData* rareData(VM& vm)
122 {
123 if (UNLIKELY(!m_rareData))
124 return allocateRareData(vm);
125 return m_rareData.get();
126 }
127
128 FunctionRareData* rareData(ExecState* exec, unsigned inlineCapacity)
129 {
130 if (UNLIKELY(!m_rareData))
131 return allocateAndInitializeRareData(exec, inlineCapacity);
132 if (UNLIKELY(!m_rareData->isObjectAllocationProfileInitialized()))
133 return initializeRareData(exec, inlineCapacity);
134 return m_rareData.get();
135 }
136
137 FunctionRareData* rareData()
138 {
139 FunctionRareData* rareData = m_rareData.get();
140
141 // The JS thread may be concurrently creating the rare data
142 // If we see it, we want to ensure it has been properly created
143 WTF::loadLoadFence();
144
145 return rareData;
146 }
147
148 bool isHostOrBuiltinFunction() const;
149 bool isBuiltinFunction() const;
150 JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
151 bool isClassConstructorFunction() const;
152
153protected:
154 JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
155 JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
156
157#if ENABLE(WEBASSEMBLY)
158 JSFunction(VM&, WebAssemblyExecutable*, JSScope*);
159#endif
160
161 void finishCreation(VM&, NativeExecutable*, int length, const String& name);
162 using Base::finishCreation;
163
164 FunctionRareData* allocateRareData(VM&);
165 FunctionRareData* allocateAndInitializeRareData(ExecState*, size_t inlineCapacity);
166 FunctionRareData* initializeRareData(ExecState*, size_t inlineCapacity);
167
168 static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
169 static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = EnumerationMode());
170 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
171
172 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
173
174 static bool deleteProperty(JSCell*, ExecState*, PropertyName);
175
176 static void visitChildren(JSCell*, SlotVisitor&);
177
178
179 static NativeExecutable* lookUpOrCreateNativeExecutable(VM&, NativeFunction, Intrinsic, NativeFunction nativeConstructor, const String& name);
180
181private:
182 static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
183 {
184 JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope, structure);
185 ASSERT(function->structure()->globalObject());
186 function->finishCreation(vm);
187 return function;
188 }
189
190 friend class LLIntOffsetsExtractor;
191
192 static EncodedJSValue argumentsGetter(ExecState*, EncodedJSValue, PropertyName);
193 static EncodedJSValue callerGetter(ExecState*, EncodedJSValue, PropertyName);
194 static EncodedJSValue lengthGetter(ExecState*, EncodedJSValue, PropertyName);
195 static EncodedJSValue nameGetter(ExecState*, EncodedJSValue, PropertyName);
196
197 WriteBarrier<ExecutableBase> m_executable;
198 WriteBarrier<FunctionRareData> m_rareData;
199};
200
201} // namespace JSC
202
203#endif // JSFunction_h
204