X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174..refs/heads/master:/runtime/JSFunction.h diff --git a/runtime/JSFunction.h b/runtime/JSFunction.h index 5553115..0b87d75 100644 --- a/runtime/JSFunction.h +++ b/runtime/JSFunction.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -24,141 +24,160 @@ #ifndef JSFunction_h #define JSFunction_h +#include "FunctionRareData.h" #include "InternalFunction.h" -#include "JSObject.h" +#include "JSCallee.h" +#include "JSScope.h" +#include "Watchpoint.h" namespace JSC { - class ExecutableBase; - class FunctionExecutable; - class FunctionPrototype; - class JSActivation; - class JSGlobalObject; - class LLIntOffsetsExtractor; - class NativeExecutable; - class SourceCode; - namespace DFG { - class SpeculativeJIT; - class JITCompiler; - } +class ExecutableBase; +class FunctionExecutable; +class FunctionPrototype; +class JSLexicalEnvironment; +class JSGlobalObject; +class LLIntOffsetsExtractor; +class NativeExecutable; +class SourceCode; +namespace DFG { +class SpeculativeJIT; +class JITCompiler; +} + +typedef std::function NativeStdFunction; + +JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); + +JS_EXPORT_PRIVATE String getCalculatedDisplayName(CallFrame*, JSObject*); + +class JSFunction : public JSCallee { + friend class JIT; + friend class DFG::SpeculativeJIT; + friend class DFG::JITCompiler; + friend class VM; + +public: + typedef JSCallee Base; + const static unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; - JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); + static size_t allocationSize(size_t inlineCapacity) + { + ASSERT_UNUSED(inlineCapacity, !inlineCapacity); + return sizeof(JSFunction); + } - JS_EXPORT_PRIVATE UString getCalculatedDisplayName(CallFrame*, JSObject*); + JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); - class JSFunction : public JSNonFinalObject { - friend class JIT; - friend class DFG::SpeculativeJIT; - friend class DFG::JITCompiler; - friend class JSGlobalData; - - public: - typedef JSNonFinalObject Base; - - JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); - - static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain) - { - JSFunction* function = new (NotNull, allocateCell(*exec->heap())) JSFunction(exec, executable, scopeChain); - ASSERT(function->structure()->globalObject()); - function->finishCreation(exec, executable, scopeChain); - return function; - } - - JS_EXPORT_PRIVATE const UString& name(ExecState*); - JS_EXPORT_PRIVATE const UString displayName(ExecState*); - const UString calculatedDisplayName(ExecState*); - - ScopeChainNode* scope() - { - ASSERT(!isHostFunctionNonInline()); - return m_scopeChain.get(); - } - // This method may be called for host functins, in which case it - // will return an arbitrary value. This should only be used for - // optimized paths in which the return value does not matter for - // host functions, and checking whether the function is a host - // function is deemed too expensive. - ScopeChainNode* scopeUnchecked() - { - return m_scopeChain.get(); - } - void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain) - { - ASSERT(!isHostFunctionNonInline()); - m_scopeChain.set(globalData, this, scopeChain); - } - - ExecutableBase* executable() const { return m_executable.get(); } - - // To call either of these methods include Executable.h - inline bool isHostFunction() const; - FunctionExecutable* jsExecutable() const; - - JS_EXPORT_PRIVATE const SourceCode* sourceCode() const; - - static JS_EXPORTDATA const ClassInfo s_info; - - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) - { - ASSERT(globalObject); - return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info); - } - - NativeFunction nativeFunction(); - NativeFunction nativeConstructor(); - - static ConstructType getConstructData(JSCell*, ConstructData&); - static CallType getCallData(JSCell*, CallData&); - - static inline size_t offsetOfScopeChain() - { - return OBJECT_OFFSETOF(JSFunction, m_scopeChain); - } - - static inline size_t offsetOfExecutable() - { - return OBJECT_OFFSETOF(JSFunction, m_executable); - } - - protected: - const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; - - JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*); - JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); - - void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name); - void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*); - - static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties); - static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); - - static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - - static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); - - static void visitChildren(JSCell*, SlotVisitor&); - - private: - friend class LLIntOffsetsExtractor; - - JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const; - - static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); - static JSValue callerGetter(ExecState*, JSValue, const Identifier&); - static JSValue lengthGetter(ExecState*, JSValue, const Identifier&); - - WriteBarrier m_executable; - WriteBarrier m_scopeChain; - }; - - inline bool JSValue::isFunction() const + static JSFunction* createWithInvalidatedReallocationWatchpoint(VM&, FunctionExecutable*, JSScope*); + JS_EXPORT_PRIVATE static JSFunction* create(VM&, JSGlobalObject*, int length, const String& name, NativeStdFunction&&, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); + + static JSFunction* create(VM&, FunctionExecutable*, JSScope*); + + static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*); + static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*, const String& name); + + JS_EXPORT_PRIVATE String name(ExecState*); + JS_EXPORT_PRIVATE String displayName(ExecState*); + const String calculatedDisplayName(ExecState*); + + ExecutableBase* executable() const { return m_executable.get(); } + + // To call either of these methods include Executable.h + bool isHostFunction() const; + FunctionExecutable* jsExecutable() const; + + JS_EXPORT_PRIVATE const SourceCode* sourceCode() const; + + DECLARE_EXPORT_INFO; + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + ASSERT(globalObject); + return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info()); + } + + NativeFunction nativeFunction(); + NativeFunction nativeConstructor(); + + static ConstructType getConstructData(JSCell*, ConstructData&); + static CallType getCallData(JSCell*, CallData&); + + static inline ptrdiff_t offsetOfExecutable() + { + return OBJECT_OFFSETOF(JSFunction, m_executable); + } + + static inline ptrdiff_t offsetOfRareData() + { + return OBJECT_OFFSETOF(JSFunction, m_rareData); + } + + FunctionRareData* rareData(ExecState* exec, unsigned inlineCapacity) + { + if (UNLIKELY(!m_rareData)) + return allocateAndInitializeRareData(exec, inlineCapacity); + if (UNLIKELY(!m_rareData->isInitialized())) + return initializeRareData(exec, inlineCapacity); + return m_rareData.get(); + } + + FunctionRareData* rareData() { - return isCell() && (asCell()->inherits(&JSFunction::s_info) || asCell()->inherits(&InternalFunction::s_info)); + FunctionRareData* rareData = m_rareData.get(); + + // The JS thread may be concurrently creating the rare data + // If we see it, we want to ensure it has been properly created + WTF::loadLoadFence(); + + return rareData; } + bool isHostOrBuiltinFunction() const; + bool isBuiltinFunction() const; + JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const; + bool isClassConstructorFunction() const; + +protected: + JS_EXPORT_PRIVATE JSFunction(VM&, JSGlobalObject*, Structure*); + JSFunction(VM&, FunctionExecutable*, JSScope*); + + void finishCreation(VM&, NativeExecutable*, int length, const String& name); + using Base::finishCreation; + + FunctionRareData* allocateAndInitializeRareData(ExecState*, size_t inlineCapacity); + FunctionRareData* initializeRareData(ExecState*, size_t inlineCapacity); + + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); + static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = EnumerationMode()); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); + + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + + static void visitChildren(JSCell*, SlotVisitor&); + +private: + static JSFunction* createImpl(VM& vm, FunctionExecutable* executable, JSScope* scope) + { + JSFunction* function = new (NotNull, allocateCell(vm.heap)) JSFunction(vm, executable, scope); + ASSERT(function->structure()->globalObject()); + function->finishCreation(vm); + return function; + } + + friend class LLIntOffsetsExtractor; + + static EncodedJSValue argumentsGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName); + static EncodedJSValue callerGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName); + static EncodedJSValue lengthGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName); + static EncodedJSValue nameGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName); + + WriteBarrier m_executable; + WriteBarrier m_rareData; +}; + } // namespace JSC #endif // JSFunction_h