1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QV4VTABLE_P_H
4#define QV4VTABLE_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include "qv4global_p.h"
18#include <QtCore/qmetaobject.h>
19
20QT_BEGIN_NAMESPACE
21
22class QObject;
23namespace QV4 {
24
25struct Lookup;
26
27struct Q_QML_PRIVATE_EXPORT OwnPropertyKeyIterator {
28 virtual ~OwnPropertyKeyIterator() = 0;
29 virtual PropertyKey next(const Object *o, Property *p = nullptr, PropertyAttributes *attrs = nullptr) = 0;
30};
31
32struct VTable
33{
34 typedef void (*Destroy)(Heap::Base *);
35 typedef void (*MarkObjects)(Heap::Base *, MarkStack *markStack);
36 typedef bool (*IsEqualTo)(Managed *m, Managed *other);
37
38 typedef ReturnedValue (*Get)(const Managed *, PropertyKey id, const Value *receiver, bool *hasProperty);
39 typedef bool (*Put)(Managed *, PropertyKey id, const Value &value, Value *receiver);
40 typedef bool (*DeleteProperty)(Managed *m, PropertyKey id);
41 typedef bool (*HasProperty)(const Managed *m, PropertyKey id);
42 typedef PropertyAttributes (*GetOwnProperty)(const Managed *m, PropertyKey id, Property *p);
43 typedef bool (*DefineOwnProperty)(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
44 typedef bool (*IsExtensible)(const Managed *);
45 typedef bool (*PreventExtensions)(Managed *);
46 typedef Heap::Object *(*GetPrototypeOf)(const Managed *);
47 typedef bool (*SetPrototypeOf)(Managed *, const Object *);
48 typedef qint64 (*GetLength)(const Managed *m);
49 typedef OwnPropertyKeyIterator *(*OwnPropertyKeys)(const Object *m, Value *target);
50 typedef ReturnedValue (*InstanceOf)(const Object *typeObject, const Value &var);
51
52 typedef ReturnedValue (*Call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
53 typedef void (*CallWithMetaTypes)(const FunctionObject *, QObject *, void **, const QMetaType *, int);
54 typedef ReturnedValue (*CallAsConstructor)(const FunctionObject *, const Value *argv, int argc, const Value *newTarget);
55
56 typedef ReturnedValue (*ResolveLookupGetter)(const Object *, ExecutionEngine *, Lookup *);
57 typedef bool (*ResolveLookupSetter)(Object *, ExecutionEngine *, Lookup *, const Value &);
58
59 typedef int (*Metacall)(Object *, QMetaObject::Call, int, void **);
60
61 const VTable * const parent;
62 quint16 inlinePropertyOffset;
63 quint16 nInlineProperties;
64 quint8 isExecutionContext;
65 quint8 isString;
66 quint8 isObject;
67 quint8 isFunctionObject;
68 quint8 isErrorObject;
69 quint8 isArrayData;
70 quint8 isStringOrSymbol;
71 quint8 type;
72 quint8 unused[4];
73 const char *className;
74
75 Destroy destroy;
76 MarkObjects markObjects;
77 IsEqualTo isEqualTo;
78
79 Get get;
80 Put put;
81 DeleteProperty deleteProperty;
82 HasProperty hasProperty;
83 GetOwnProperty getOwnProperty;
84 DefineOwnProperty defineOwnProperty;
85 IsExtensible isExtensible;
86 PreventExtensions preventExtensions;
87 GetPrototypeOf getPrototypeOf;
88 SetPrototypeOf setPrototypeOf;
89 GetLength getLength;
90 OwnPropertyKeys ownPropertyKeys;
91 InstanceOf instanceOf;
92
93 Call call;
94 CallAsConstructor callAsConstructor;
95 CallWithMetaTypes callWithMetaTypes;
96
97 ResolveLookupGetter resolveLookupGetter;
98 ResolveLookupSetter resolveLookupSetter;
99
100 Metacall metacall;
101};
102
103template<VTable::CallWithMetaTypes call>
104struct VTableCallWithMetaTypesWrapper { constexpr static VTable::CallWithMetaTypes c = call; };
105
106template<VTable::Call call>
107struct VTableCallWrapper { constexpr static VTable::Call c = call; };
108
109template<class Class>
110constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry()
111{
112 // If Class overrides virtualCallWithMetaTypes, return that.
113 // Otherwise, if it overrides virtualCall, return nullptr so that we convert calls.
114 // Otherwise, just return whatever the base class had.
115
116 // A simple != is not considered constexpr, so we have to jump through some hoops.
117 if constexpr (!std::is_same_v<
118 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
119 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) {
120 return Class::virtualCallWithMetaTypes;
121 }
122
123 if constexpr (!std::is_same_v<
124 VTableCallWrapper<Class::virtualCall>,
125 VTableCallWrapper<Class::SuperClass::virtualCall>>) {
126 return nullptr;
127 }
128
129 return Class::virtualCallWithMetaTypes;
130}
131
132template<class Class>
133constexpr VTable::Call vtableJsTypesCallEntry()
134{
135 // If Class overrides virtualCall, return that.
136 // Otherwise, if it overrides virtualCallWithMetaTypes, return nullptr so that we convert calls.
137 // Otherwise, just return whatever the base class had.
138
139 // A simple != is not considered constexpr, so we have to jump through some hoops.
140 if constexpr (!std::is_same_v<
141 VTableCallWrapper<Class::virtualCall>,
142 VTableCallWrapper<Class::SuperClass::virtualCall>>) {
143 return Class::virtualCall;
144 }
145
146 if constexpr (!std::is_same_v<
147 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
148 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) {
149 return nullptr;
150 }
151
152 return Class::virtualCall;
153}
154
155struct VTableBase {
156protected:
157 static constexpr VTable::Destroy virtualDestroy = nullptr;
158 static constexpr VTable::IsEqualTo virtualIsEqualTo = nullptr;
159
160 static constexpr VTable::Get virtualGet = nullptr;
161 static constexpr VTable::Put virtualPut = nullptr;
162 static constexpr VTable::DeleteProperty virtualDeleteProperty = nullptr;
163 static constexpr VTable::HasProperty virtualHasProperty = nullptr;
164 static constexpr VTable::GetOwnProperty virtualGetOwnProperty = nullptr;
165 static constexpr VTable::DefineOwnProperty virtualDefineOwnProperty = nullptr;
166 static constexpr VTable::IsExtensible virtualIsExtensible = nullptr;
167 static constexpr VTable::PreventExtensions virtualPreventExtensions = nullptr;
168 static constexpr VTable::GetPrototypeOf virtualGetPrototypeOf = nullptr;
169 static constexpr VTable::SetPrototypeOf virtualSetPrototypeOf = nullptr;
170 static constexpr VTable::GetLength virtualGetLength = nullptr;
171 static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys = nullptr;
172 static constexpr VTable::InstanceOf virtualInstanceOf = nullptr;
173
174 static constexpr VTable::Call virtualCall = nullptr;
175 static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr;
176 static constexpr VTable::CallWithMetaTypes virtualCallWithMetaTypes = nullptr;
177
178 static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter = nullptr;
179 static constexpr VTable::ResolveLookupSetter virtualResolveLookupSetter = nullptr;
180
181 static constexpr VTable::Metacall virtualMetacall = nullptr;
182
183 template<class Class>
184 friend constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry();
185
186 template<class Class>
187 friend constexpr VTable::Call vtableJsTypesCallEntry();
188};
189
190#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
191{ \
192 parentVTable, \
193 (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
194 (sizeof(classname::Data) + (classname::NInlineProperties*sizeof(QV4::Value)) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
195 - (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
196 classname::IsExecutionContext, \
197 classname::IsString, \
198 classname::IsObject, \
199 classname::IsFunctionObject, \
200 classname::IsErrorObject, \
201 classname::IsArrayData, \
202 classname::IsStringOrSymbol, \
203 classname::MyType, \
204 { 0, 0, 0, 0 }, \
205 #classname, \
206 \
207 classname::virtualDestroy, \
208 classname::Data::markObjects, \
209 classname::virtualIsEqualTo, \
210 \
211 classname::virtualGet, \
212 classname::virtualPut, \
213 classname::virtualDeleteProperty, \
214 classname::virtualHasProperty, \
215 classname::virtualGetOwnProperty, \
216 classname::virtualDefineOwnProperty, \
217 classname::virtualIsExtensible, \
218 classname::virtualPreventExtensions, \
219 classname::virtualGetPrototypeOf, \
220 classname::virtualSetPrototypeOf, \
221 classname::virtualGetLength, \
222 classname::virtualOwnPropertyKeys, \
223 classname::virtualInstanceOf, \
224 \
225 QV4::vtableJsTypesCallEntry<classname>(), \
226 classname::virtualCallAsConstructor, \
227 QV4::vtableMetaTypesCallEntry<classname>(), \
228 \
229 classname::virtualResolveLookupGetter, \
230 classname::virtualResolveLookupSetter, \
231 classname::virtualMetacall \
232}
233
234#define DEFINE_MANAGED_VTABLE(classname) \
235const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
236
237#define V4_OBJECT2(DataClass, superClass) \
238 private: \
239 DataClass() = delete; \
240 Q_DISABLE_COPY(DataClass) \
241 public: \
242 Q_MANAGED_CHECK \
243 typedef QV4::Heap::DataClass Data; \
244 typedef superClass SuperClass; \
245 static const QV4::VTable static_vtbl; \
246 static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
247 V4_MANAGED_SIZE_TEST \
248 QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
249 QV4::Heap::DataClass *d() const { \
250 QV4::Heap::DataClass *dptr = d_unchecked(); \
251 dptr->_checkIsInitialized(); \
252 return dptr; \
253 } \
254 Q_STATIC_ASSERT(std::is_trivial_v<QV4::Heap::DataClass>);
255
256#define V4_PROTOTYPE(p) \
257 static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
258 { return e->p(); }
259
260
261#define DEFINE_OBJECT_VTABLE_BASE(classname) \
262 const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? nullptr : &classname::SuperClass::static_vtbl)
263
264#define DEFINE_OBJECT_VTABLE(classname) \
265DEFINE_OBJECT_VTABLE_BASE(classname)
266
267#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \
268template<> DEFINE_OBJECT_VTABLE_BASE(classname)
269
270}
271
272QT_END_NAMESPACE
273
274#endif
275

source code of qtdeclarative/src/qml/jsruntime/qv4vtable_p.h