1/*
2 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 *  Copyright (C) 2003, 2006, 2007, 2008, 2009 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 "InternalFunction.h"
28#include "JSDestructibleObject.h"
29#include "JSScope.h"
30#include "ObjectAllocationProfile.h"
31#include "Watchpoint.h"
32
33namespace JSC {
34
35    class ExecutableBase;
36    class FunctionExecutable;
37    class FunctionPrototype;
38    class JSActivation;
39    class JSGlobalObject;
40    class LLIntOffsetsExtractor;
41    class NativeExecutable;
42    class SourceCode;
43    namespace DFG {
44    class SpeculativeJIT;
45    class JITCompiler;
46    }
47
48    JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
49
50    JS_EXPORT_PRIVATE String getCalculatedDisplayName(CallFrame*, JSObject*);
51
52    class JSFunction : public JSDestructibleObject {
53        friend class JIT;
54        friend class DFG::SpeculativeJIT;
55        friend class DFG::JITCompiler;
56        friend class VM;
57
58    public:
59        typedef JSDestructibleObject Base;
60
61        JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor);
62
63        static JSFunction* create(VM& vm, FunctionExecutable* executable, JSScope* scope)
64        {
65            JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
66            ASSERT(function->structure()->globalObject());
67            function->finishCreation(vm);
68            return function;
69        }
70
71        static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
72
73        static void destroy(JSCell*);
74
75        JS_EXPORT_PRIVATE String name(ExecState*);
76        JS_EXPORT_PRIVATE String displayName(ExecState*);
77        const String calculatedDisplayName(ExecState*);
78
79        JSScope* scope()
80        {
81            ASSERT(!isHostFunctionNonInline());
82            return m_scope.get();
83        }
84        // This method may be called for host functins, in which case it
85        // will return an arbitrary value. This should only be used for
86        // optimized paths in which the return value does not matter for
87        // host functions, and checking whether the function is a host
88        // function is deemed too expensive.
89        JSScope* scopeUnchecked()
90        {
91            return m_scope.get();
92        }
93        void setScope(VM& vm, JSScope* scope)
94        {
95            ASSERT(!isHostFunctionNonInline());
96            m_scope.set(vm, this, scope);
97        }
98        void addNameScopeIfNeeded(VM&);
99
100        ExecutableBase* executable() const { return m_executable.get(); }
101
102        // To call either of these methods include Executable.h
103        bool isHostFunction() const;
104        FunctionExecutable* jsExecutable() const;
105
106        JS_EXPORT_PRIVATE const SourceCode* sourceCode() const;
107
108        DECLARE_EXPORT_INFO;
109
110        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
111        {
112            ASSERT(globalObject);
113            return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
114        }
115
116        NativeFunction nativeFunction();
117        NativeFunction nativeConstructor();
118
119        static ConstructType getConstructData(JSCell*, ConstructData&);
120        static CallType getCallData(JSCell*, CallData&);
121
122        static inline ptrdiff_t offsetOfScopeChain()
123        {
124            return OBJECT_OFFSETOF(JSFunction, m_scope);
125        }
126
127        static inline ptrdiff_t offsetOfExecutable()
128        {
129            return OBJECT_OFFSETOF(JSFunction, m_executable);
130        }
131
132        static inline ptrdiff_t offsetOfAllocationProfile()
133        {
134            return OBJECT_OFFSETOF(JSFunction, m_allocationProfile);
135        }
136
137        ObjectAllocationProfile* allocationProfile(ExecState* exec, unsigned inlineCapacity)
138        {
139            if (UNLIKELY(m_allocationProfile.isNull()))
140                return createAllocationProfile(exec, inlineCapacity);
141            return &m_allocationProfile;
142        }
143
144        Structure* allocationStructure() { return m_allocationProfile.structure(); }
145
146        InlineWatchpointSet& allocationProfileWatchpointSet()
147        {
148            return m_allocationProfileWatchpoint;
149        }
150
151        bool isHostOrBuiltinFunction() const;
152        bool isBuiltinFunction() const;
153        JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
154
155    protected:
156        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
157
158        JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*);
159        JSFunction(VM&, FunctionExecutable*, JSScope*);
160
161        void finishCreation(VM&, NativeExecutable*, int length, const String& name);
162        using Base::finishCreation;
163
164        ObjectAllocationProfile* createAllocationProfile(ExecState*, size_t inlineCapacity);
165
166        static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
167        static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties);
168        static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
169
170        static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
171
172        static bool deleteProperty(JSCell*, ExecState*, PropertyName);
173
174        static void visitChildren(JSCell*, SlotVisitor&);
175
176    private:
177        friend class LLIntOffsetsExtractor;
178
179        static EncodedJSValue argumentsGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
180        static EncodedJSValue callerGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
181        static EncodedJSValue lengthGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
182        static EncodedJSValue nameGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
183
184        WriteBarrier<ExecutableBase> m_executable;
185        WriteBarrier<JSScope> m_scope;
186        ObjectAllocationProfile m_allocationProfile;
187        InlineWatchpointSet m_allocationProfileWatchpoint;
188    };
189
190} // namespace JSC
191
192#endif // JSFunction_h
193