InternalFunction.h [plain text]
#pragma once
#include "CodeSpecializationKind.h"
#include "JSCPoison.h"
#include "JSDestructibleObject.h"
namespace JSC {
class FunctionPrototype;
class InternalFunction : public JSDestructibleObject {
friend class JIT;
friend class LLIntOffsetsExtractor;
public:
typedef JSDestructibleObject Base;
static const unsigned StructureFlags = Base::StructureFlags | ImplementsHasInstance | ImplementsDefaultHasInstance | OverridesGetCallData;
template<typename CellType>
static IsoSubspace* subspaceFor(VM& vm)
{
static_assert(sizeof(CellType) == sizeof(InternalFunction), "InternalFunction subclasses that add fields need to override subspaceFor<>()");
return &vm.internalFunctionSpace;
}
DECLARE_EXPORT_INFO;
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
JS_EXPORT_PRIVATE const String& name();
const String displayName(VM&);
const String calculatedDisplayName(VM&);
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
{
return Structure::create(vm, globalObject, proto, TypeInfo(InternalFunctionType, StructureFlags), info());
}
static Structure* createSubclassStructure(ExecState*, JSValue newTarget, Structure*);
TaggedNativeFunction nativeFunctionFor(CodeSpecializationKind kind)
{
if (kind == CodeForCall)
return m_functionForCall.unpoisoned();
ASSERT(kind == CodeForConstruct);
return m_functionForConstruct.unpoisoned();
}
static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
{
if (kind == CodeForCall)
return OBJECT_OFFSETOF(InternalFunction, m_functionForCall);
ASSERT(kind == CodeForConstruct);
return OBJECT_OFFSETOF(InternalFunction, m_functionForConstruct);
}
protected:
using PoisonedTaggedNativeFunction = Poisoned<NativeCodePoison, TaggedNativeFunction>;
JS_EXPORT_PRIVATE InternalFunction(VM&, Structure*, NativeFunction functionForCall, NativeFunction functionForConstruct);
enum class NameVisibility { Visible, Anonymous };
JS_EXPORT_PRIVATE void finishCreation(VM&, const String& name, NameVisibility = NameVisibility::Visible);
JS_EXPORT_PRIVATE static Structure* createSubclassStructureSlow(ExecState*, JSValue newTarget, Structure*);
JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
PoisonedTaggedNativeFunction m_functionForCall;
PoisonedTaggedNativeFunction m_functionForConstruct;
WriteBarrier<JSString> m_originalName;
};
ALWAYS_INLINE Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
{
ASSERT(!newTarget || newTarget.isConstructor(exec->vm()));
if (newTarget && newTarget != exec->jsCallee())
return createSubclassStructureSlow(exec, newTarget, baseClass);
return baseClass;
}
}