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_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 isTailCallable;
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 convertAndCall.
114 // Otherwise, just return whatever the base class had.
115
116 // A simple == on methods is not considered constexpr, so we have to jump through some hoops.
117
118 static_assert(
119 std::is_same_v<
120 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
121 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>
122 || !std::is_same_v<
123 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
124 VTableCallWithMetaTypesWrapper<nullptr>>,
125 "You mustn't override virtualCallWithMetaTypes with nullptr");
126
127 static_assert(
128 std::is_same_v<
129 VTableCallWithMetaTypesWrapper<Class::virtualConvertAndCall>,
130 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualConvertAndCall>>
131 || !std::is_same_v<
132 VTableCallWithMetaTypesWrapper<Class::virtualConvertAndCall>,
133 VTableCallWithMetaTypesWrapper<nullptr>>,
134 "You mustn't override virtualConvertAndCall with nullptr");
135
136 if constexpr (
137 std::is_same_v<
138 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
139 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>
140 && !std::is_same_v<
141 VTableCallWrapper<Class::virtualCall>,
142 VTableCallWrapper<Class::SuperClass::virtualCall>>) {
143 // Converting from metatypes to JS signature is easy.
144 return Class::virtualConvertAndCall;
145 }
146
147 return Class::virtualCallWithMetaTypes;
148}
149
150template<class Class>
151constexpr VTable::Call vtableJsTypesCallEntry()
152{
153 // If Class overrides virtualCall, return that.
154 // Otherwise, if it overrides virtualCallWithMetaTypes, fail.
155 // (We cannot determine the target types to call virtualCallWithMetaTypes in that case)
156 // Otherwise, just return whatever the base class had.
157
158 // A simple == on methods is not considered constexpr, so we have to jump through some hoops.
159
160 static_assert(
161 !std::is_same_v<
162 VTableCallWrapper<Class::virtualCall>,
163 VTableCallWrapper<Class::SuperClass::virtualCall>>
164 || std::is_same_v<
165 VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
166 VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>,
167 "If you override virtualCallWithMetaTypes, override virtualCall, too");
168
169 static_assert(
170 std::is_same_v<
171 VTableCallWrapper<Class::virtualCall>,
172 VTableCallWrapper<Class::SuperClass::virtualCall>>
173 || VTableCallWrapper<Class::virtualCall>::c != nullptr,
174 "You mustn't override virtualCall with nullptr");
175
176 return Class::virtualCall;
177}
178
179struct VTableBase {
180protected:
181 static constexpr VTable::Destroy virtualDestroy = nullptr;
182 static constexpr VTable::IsEqualTo virtualIsEqualTo = nullptr;
183
184 static constexpr VTable::Get virtualGet = nullptr;
185 static constexpr VTable::Put virtualPut = nullptr;
186 static constexpr VTable::DeleteProperty virtualDeleteProperty = nullptr;
187 static constexpr VTable::HasProperty virtualHasProperty = nullptr;
188 static constexpr VTable::GetOwnProperty virtualGetOwnProperty = nullptr;
189 static constexpr VTable::DefineOwnProperty virtualDefineOwnProperty = nullptr;
190 static constexpr VTable::IsExtensible virtualIsExtensible = nullptr;
191 static constexpr VTable::PreventExtensions virtualPreventExtensions = nullptr;
192 static constexpr VTable::GetPrototypeOf virtualGetPrototypeOf = nullptr;
193 static constexpr VTable::SetPrototypeOf virtualSetPrototypeOf = nullptr;
194 static constexpr VTable::GetLength virtualGetLength = nullptr;
195 static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys = nullptr;
196 static constexpr VTable::InstanceOf virtualInstanceOf = nullptr;
197
198 static constexpr VTable::Call virtualCall = nullptr;
199 static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr;
200 static constexpr VTable::CallWithMetaTypes virtualCallWithMetaTypes = nullptr;
201 static constexpr VTable::CallWithMetaTypes virtualConvertAndCall = nullptr;
202
203 static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter = nullptr;
204 static constexpr VTable::ResolveLookupSetter virtualResolveLookupSetter = nullptr;
205
206 static constexpr VTable::Metacall virtualMetacall = nullptr;
207
208 template<class Class>
209 friend constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry();
210
211 template<class Class>
212 friend constexpr VTable::Call vtableJsTypesCallEntry();
213};
214
215#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
216{ \
217 parentVTable, \
218 (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
219 (sizeof(classname::Data) + (classname::NInlineProperties*sizeof(QV4::Value)) + QV4::Chunk::SlotSize - 1)/QV4::Chunk::SlotSize*QV4::Chunk::SlotSize/sizeof(QV4::Value) \
220 - (sizeof(classname::Data) + sizeof(QV4::Value) - 1)/sizeof(QV4::Value), \
221 classname::IsExecutionContext, \
222 classname::IsString, \
223 classname::IsObject, \
224 classname::IsTailCallable, \
225 classname::IsErrorObject, \
226 classname::IsArrayData, \
227 classname::IsStringOrSymbol, \
228 classname::MyType, \
229 { 0, 0, 0, 0 }, \
230 #classname, \
231 \
232 classname::virtualDestroy, \
233 classname::Data::markObjects, \
234 classname::virtualIsEqualTo, \
235 \
236 classname::virtualGet, \
237 classname::virtualPut, \
238 classname::virtualDeleteProperty, \
239 classname::virtualHasProperty, \
240 classname::virtualGetOwnProperty, \
241 classname::virtualDefineOwnProperty, \
242 classname::virtualIsExtensible, \
243 classname::virtualPreventExtensions, \
244 classname::virtualGetPrototypeOf, \
245 classname::virtualSetPrototypeOf, \
246 classname::virtualGetLength, \
247 classname::virtualOwnPropertyKeys, \
248 classname::virtualInstanceOf, \
249 \
250 QV4::vtableJsTypesCallEntry<classname>(), \
251 classname::virtualCallAsConstructor, \
252 QV4::vtableMetaTypesCallEntry<classname>(), \
253 \
254 classname::virtualResolveLookupGetter, \
255 classname::virtualResolveLookupSetter, \
256 classname::virtualMetacall \
257}
258
259#define DEFINE_MANAGED_VTABLE(classname) \
260const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
261
262#define V4_OBJECT2(DataClass, superClass) \
263 private: \
264 DataClass() = delete; \
265 Q_DISABLE_COPY(DataClass) \
266 public: \
267 Q_MANAGED_CHECK \
268 typedef QV4::Heap::DataClass Data; \
269 typedef superClass SuperClass; \
270 static const QV4::VTable static_vtbl; \
271 static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
272 V4_MANAGED_SIZE_TEST \
273 QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
274 QV4::Heap::DataClass *d() const { \
275 QV4::Heap::DataClass *dptr = d_unchecked(); \
276 dptr->_checkIsInitialized(); \
277 return dptr; \
278 } \
279 Q_STATIC_ASSERT(std::is_trivial_v<QV4::Heap::DataClass>);
280
281#define V4_PROTOTYPE(p) \
282 static QV4::Object *defaultPrototype(QV4::ExecutionEngine *e) \
283 { return e->p(); }
284
285
286#define DEFINE_OBJECT_VTABLE_BASE(classname) \
287 const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, (std::is_same<classname::SuperClass, Object>::value) ? nullptr : &classname::SuperClass::static_vtbl)
288
289#define DEFINE_OBJECT_VTABLE(classname) \
290DEFINE_OBJECT_VTABLE_BASE(classname)
291
292#define DEFINE_OBJECT_TEMPLATE_VTABLE(classname) \
293template<> DEFINE_OBJECT_VTABLE_BASE(classname)
294
295}
296
297QT_END_NAMESPACE
298
299#endif
300

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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