1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003-2019 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#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 const 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(ExecState*, 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
78protected:
79 JS_EXPORT_PRIVATE InternalFunction(VM&, Structure*, NativeFunction functionForCall, NativeFunction functionForConstruct);
80
81 enum class NameVisibility { Visible, Anonymous };
82 enum class NameAdditionMode { WithStructureTransition, WithoutStructureTransition };
83 JS_EXPORT_PRIVATE void finishCreation(VM&, const String& name, NameVisibility = NameVisibility::Visible, NameAdditionMode = NameAdditionMode::WithStructureTransition);
84
85 JS_EXPORT_PRIVATE static Structure* createSubclassStructureSlow(ExecState*, JSValue newTarget, Structure*);
86
87 JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
88 JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
89
90 TaggedNativeFunction m_functionForCall;
91 TaggedNativeFunction m_functionForConstruct;
92 WriteBarrier<JSString> m_originalName;
93};
94
95ALWAYS_INLINE Structure* InternalFunction::createSubclassStructure(ExecState* exec, JSValue newTarget, Structure* baseClass)
96{
97 // We allow newTarget == JSValue() because the API needs to be able to create classes without having a real JS frame.
98 // Since we don't allow subclassing in the API we just treat newTarget == JSValue() as newTarget == exec->jsCallee()
99 ASSERT(!newTarget || newTarget.isConstructor(exec->vm()));
100
101 if (newTarget && newTarget != exec->jsCallee())
102 return createSubclassStructureSlow(exec, newTarget, baseClass);
103 return baseClass;
104}
105
106} // namespace JSC
107