1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2003-2019 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Cameron Zwarich ([email protected])
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 "CodeSpecializationKind.h"
27#include "JSDestructibleObject.h"
28
29namespace JSC {
30
31class FunctionPrototype;
32
33class InternalFunction : public JSDestructibleObject {
34 friend class JIT;
35 friend class LLIntOffsetsExtractor;
36public:
37 typedef JSDestructibleObject Base;
38 static constexpr unsigned StructureFlags = Base::StructureFlags | ImplementsHasInstance | ImplementsDefaultHasInstance | OverridesGetCallData;
39
40 template<typename CellType, SubspaceAccess>
41 static IsoSubspace* subspaceFor(VM& vm)
42 {
43 static_assert(sizeof(CellType) == sizeof(InternalFunction), "InternalFunction subclasses that add fields need to override subspaceFor<>()");
44 return &vm.internalFunctionSpace;
45 }
46
47 DECLARE_EXPORT_INFO;
48
49 JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
50
51 JS_EXPORT_PRIVATE const String& name();
52 const String displayName(VM&);
53 const String calculatedDisplayName(VM&);
54
55 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
56 {
57 return Structure::create(vm, globalObject, proto, TypeInfo(InternalFunctionType, StructureFlags), info());
58 }
59
60 static Structure* createSubclassStructure(JSGlobalObject*, JSObject* baseCallee, JSValue newTarget, Structure*);
61
62 TaggedNativeFunction nativeFunctionFor(CodeSpecializationKind kind)
63 {
64 if (kind == CodeForCall)
65 return m_functionForCall;
66 ASSERT(kind == CodeForConstruct);
67 return m_functionForConstruct;
68 }
69
70 static ptrdiff_t offsetOfNativeFunctionFor(CodeSpecializationKind kind)
71 {
72 if (kind == CodeForCall)
73 return OBJECT_OFFSETOF(InternalFunction, m_functionForCall);
74 ASSERT(kind == CodeForConstruct);
75 return OBJECT_OFFSETOF(InternalFunction, m_functionForConstruct);
76 }
77
78 static ptrdiff_t offsetOfGlobalObject()
79 {
80 return OBJECT_OFFSETOF(InternalFunction, m_globalObject);
81 }
82
83 JSGlobalObject* globalObject() const { return m_globalObject.get(); }
84
85protected:
86 JS_EXPORT_PRIVATE InternalFunction(VM&, Structure*, NativeFunction functionForCall, NativeFunction functionForConstruct);
87
88 enum class NameAdditionMode { WithStructureTransition, WithoutStructureTransition };
89 JS_EXPORT_PRIVATE void finishCreation(VM&, const String& name, NameAdditionMode = NameAdditionMode::WithStructureTransition);
90
91 JS_EXPORT_PRIVATE static Structure* createSubclassStructureSlow(JSGlobalObject*, JSValue newTarget, Structure*);
92
93 JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
94 JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
95
96 TaggedNativeFunction m_functionForCall;
97 TaggedNativeFunction m_functionForConstruct;
98 WriteBarrier<JSString> m_originalName;
99 WriteBarrier<JSGlobalObject> m_globalObject;
100};
101
102ALWAYS_INLINE Structure* InternalFunction::createSubclassStructure(JSGlobalObject* globalObject, JSObject* baseCallee, JSValue newTarget, Structure* baseClass)
103{
104 // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
105 // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == callFrame->jsCallee()
106 if (newTarget && newTarget != baseCallee)
107 return createSubclassStructureSlow(globalObject, newTarget, baseClass);
108 return baseClass;
109}
110
111} // namespace JSC
112