Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmldata_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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
4#ifndef QQMLDATA_P_H
5#define QQMLDATA_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qtqmlglobal_p.h>
19#include <private/qobject_p.h>
20#include <private/qqmlpropertyindex_p.h>
21#include <private/qv4value_p.h>
22#include <private/qv4persistent_p.h>
23#include <private/qqmlrefcount_p.h>
24#include <private/qqmlpropertycache_p.h>
25#include <qqmlprivate.h>
26#include <qjsengine.h>
27#include <qvector.h>
28
30
31template <class Key, class T> class QHash;
32class QQmlEngine;
33class QQmlGuardImpl;
35class QQmlBoundSignal;
36class QQmlContext;
38class QQmlContextData;
39class QQmlNotifier;
43
44namespace QV4 {
45class ExecutableCompilationUnit;
46namespace CompiledData {
47struct Binding;
48}
49}
50
51// This class is structured in such a way, that simply zero'ing it is the
52// default state for elemental object allocations. This is crucial in the
53// workings of the QQmlInstruction::CreateSimpleObject instruction.
54// Don't change anything here without first considering that case!
55class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
56{
57public:
58 enum Ownership { DoesNotOwnMemory, OwnsMemory };
59
60 QQmlData(Ownership ownership);
61 ~QQmlData();
62
63 static inline void init() {
64 static bool initialized = false;
65 if (!initialized) {
66 initialized = true;
71 }
72 }
73
75 static void signalEmitted(QAbstractDeclarativeData *, QObject *, int, void **);
76 static int receivers(QAbstractDeclarativeData *, const QObject *, int);
77 static bool isSignalConnected(QAbstractDeclarativeData *, const QObject *, int);
78
79 void destroyed(QObject *);
80
82 if (!explicitIndestructibleSet) indestructible = false;
83 }
84
85 // If ownMemomry is true, the QQmlData was normally allocated. Otherwise it was allocated
86 // with placement new and QQmlData::destroyed is not allowed to free the memory
88 // indestructible is set if and only if the object has CppOwnership
89 // This can be explicitly set with QJSEngine::setObjectOwnership
90 // Top level objects generally have CppOwnership (see QQmlcCmponentprivate::beginCreate),
91 // unless created by special methods like the QML component.createObject() function
93 // indestructible was explicitly set with setObjectOwnership
94 // or the object is a top-level object
96 // set when one QObject has been wrapped into QObjectWrapper in multiple engines
97 // at the same time - a rather rare case
100 /*
101 * rootObjectInCreation should be true only when creating top level CPP and QML objects,
102 * v4 GC will check this flag, only deletes the objects when rootObjectInCreation is false.
103 */
105 // set when at least one of the object's properties is intercepted
108 // If we have another wrapper for a const QObject * in the multiply wrapped QObjects.
111
112 // When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside
113 // bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated
114 // sufficient space and use bindingBits to point to it.
117 enum {
118 BitsPerType = sizeof(BindingBitsType) * 8,
119 InlineBindingArraySize = 2
120 };
121 union {
123 BindingBitsType bindingBitsValue[InlineBindingArraySize];
124 };
125
126 struct NotifyList {
128
131
134 void layout();
135 private:
137 };
138 NotifyList *notifyList = nullptr;
139
140 inline QQmlNotifierEndpoint *notify(int index);
141 void addNotify(int index, QQmlNotifierEndpoint *);
142 int endpointCount(int index);
143 bool signalHasEndpoint(int index) const;
144 void disconnectNotifiers();
145
146 // The context that created the C++ object; not refcounted to prevent cycles
148 // The outermost context in which this object lives; not refcounted to prevent cycles
149 QQmlContextData *outerContext = nullptr;
151
152 QQmlAbstractBinding *bindings = nullptr;
153 QQmlBoundSignal *signalHandlers = nullptr;
154 std::vector<QQmlPropertyObserver> propertyObservers;
155
156 // Linked list for QQmlContext::contextObjects
157 QQmlData *nextContextObject = nullptr;
158 QQmlData**prevContextObject = nullptr;
159
160 inline bool hasBindingBit(int) const;
161 inline void setBindingBit(QObject *obj, int);
162 inline void clearBindingBit(int);
163
164 inline bool hasPendingBindingBit(int index) const;
165 inline void setPendingBindingBit(QObject *obj, int);
166 inline void clearPendingBindingBit(int);
167
168 quint16 lineNumber = 0;
169 quint16 columnNumber = 0;
170
171 quint32 jsEngineId = 0; // id of the engine that created the jsWrapper
172
176 unsigned int deferredIdx;
178
179 // Not always the same as the other compilation unit
181
182 // Could be either context or outerContext
185 };
188
189 void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &,
191 void releaseDeferredData();
192
194
196
197 QQmlGuardImpl *guards = 0;
198
200 // If QObjectData::isDeletingChildren is set then access to QObjectPrivate::declarativeData has
201 // to be avoided because QObjectPrivate::currentChildBeingDeleted is in use.
202 if (priv->isDeletingChildren || priv->wasDeleted) {
204 return nullptr;
205 } else if (priv->declarativeData) {
206 return static_cast<QQmlData *>(priv->declarativeData);
207 } else if (create) {
208 return createQQmlData(priv);
209 } else {
210 return nullptr;
211 }
212 }
213
214 static QQmlData *get(const QObjectPrivate *priv) {
215 // If QObjectData::isDeletingChildren is set then access to QObjectPrivate::declarativeData has
216 // to be avoided because QObjectPrivate::currentChildBeingDeleted is in use.
217 if (priv->isDeletingChildren || priv->wasDeleted)
218 return nullptr;
219 if (priv->declarativeData)
220 return static_cast<QQmlData *>(priv->declarativeData);
221 return nullptr;
222 }
223
224 static QQmlData *get(QObject *object, bool create) {
226 }
227
228 static QQmlData *get(const QObject *object) {
229 return QQmlData::get(QObjectPrivate::get(object));
230
231 }
232
233 static bool keepAliveDuringGarbageCollection(const QObject *object) {
234 QQmlData *ddata = get(object);
235 if (!ddata || ddata->indestructible || ddata->rootObjectInCreation)
236 return true;
237 return false;
238 }
239
240 bool hasExtendedData() const { return extendedData != nullptr; }
241 QHash<QQmlAttachedPropertiesFunc, QObject *> *attachedProperties() const;
242
243 static inline bool wasDeleted(const QObject *);
244 static inline bool wasDeleted(const QObjectPrivate *);
245
246 static void markAsDeleted(QObject *);
247 static void setQueuedForDeletion(QObject *);
248
249 static inline void flushPendingBinding(QObject *object, int coreIndex);
250 void flushPendingBinding(int coreIndex);
251
253 {
254 QQmlData *ddata = QQmlData::get(object, /*create*/true);
255 if (Q_LIKELY(ddata->propertyCache))
256 return ddata->propertyCache;
257 return createPropertyCache(object);
258 }
259
260 Q_ALWAYS_INLINE static uint offsetForBit(int bit) { return static_cast<uint>(bit) / BitsPerType; }
261 Q_ALWAYS_INLINE static BindingBitsType bitFlagForBit(int bit) { return BindingBitsType(1) << (static_cast<uint>(bit) & (BitsPerType - 1)); }
262
263private:
264 // For attachedProperties
265 mutable QQmlDataExtended *extendedData = nullptr;
266
267 Q_NEVER_INLINE static QQmlData *createQQmlData(QObjectPrivate *priv);
268 Q_NEVER_INLINE static QQmlPropertyCache::ConstPtr createPropertyCache(QObject *object);
269
270 Q_ALWAYS_INLINE bool hasBitSet(int bit) const
271 {
272 uint offset = offsetForBit(bit);
273 if (bindingBitsArraySize <= offset)
274 return false;
275
276 const BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
277 return bits[offset] & bitFlagForBit(bit);
278 }
279
280 Q_ALWAYS_INLINE void clearBit(int bit)
281 {
283 if (bindingBitsArraySize > offset) {
284 BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
285 bits[offset] &= ~QQmlData::bitFlagForBit(bit);
286 }
287 }
288
289 Q_ALWAYS_INLINE void setBit(QObject *obj, int bit)
290 {
292 BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
293 if (Q_UNLIKELY(bindingBitsArraySize <= offset))
294 bits = growBits(obj, bit);
296 }
297
298 Q_NEVER_INLINE BindingBitsType *growBits(QObject *obj, int bit);
299
300 Q_DISABLE_COPY_MOVE(QQmlData);
301};
302
304{
305 if (!priv || priv->wasDeleted || priv->isDeletingChildren)
306 return true;
307
308 const QQmlData *ddata = QQmlData::get(priv);
309 return ddata && ddata->isQueuedForDeletion;
310}
311
312bool QQmlData::wasDeleted(const QObject *object)
313{
314 if (!object)
315 return true;
316
317 const QObjectPrivate *priv = QObjectPrivate::get(object);
319}
320
322{
323 Q_ASSERT(index <= 0xFFFF);
324
325 if (!notifyList || !(notifyList->connectionMask & (1ULL << quint64(index % 64)))) {
326 return nullptr;
327 } else if (index < notifyList->notifiesSize) {
328 return notifyList->notifies[index];
329 } else if (index <= notifyList->maximumTodoIndex) {
331 }
332
333 if (index < notifyList->notifiesSize) {
334 return notifyList->notifies[index];
335 } else {
336 return nullptr;
337 }
338}
339
340/*
341 The index MUST be in the range returned by QObjectPrivate::signalIndex()
342 This is different than the index returned by QMetaMethod::methodIndex()
343*/
344inline bool QQmlData::signalHasEndpoint(int index) const
345{
346 return notifyList && (notifyList->connectionMask & (1ULL << quint64(index % 64)));
347}
348
349bool QQmlData::hasBindingBit(int coreIndex) const
350{
351 Q_ASSERT(coreIndex >= 0);
352 Q_ASSERT(coreIndex <= 0xffff);
353
354 return hasBitSet(coreIndex * 2);
355}
356
358{
359 Q_ASSERT(coreIndex >= 0);
360 Q_ASSERT(coreIndex <= 0xffff);
361 setBit(obj, coreIndex * 2);
362}
363
364void QQmlData::clearBindingBit(int coreIndex)
365{
366 Q_ASSERT(coreIndex >= 0);
367 Q_ASSERT(coreIndex <= 0xffff);
368 clearBit(coreIndex * 2);
369}
370
371bool QQmlData::hasPendingBindingBit(int coreIndex) const
372{
373 Q_ASSERT(coreIndex >= 0);
374 Q_ASSERT(coreIndex <= 0xffff);
375
376 return hasBitSet(coreIndex * 2 + 1);
377}
378
380{
381 Q_ASSERT(coreIndex >= 0);
382 Q_ASSERT(coreIndex <= 0xffff);
383 setBit(obj, coreIndex * 2 + 1);
384}
385
387{
388 Q_ASSERT(coreIndex >= 0);
389 Q_ASSERT(coreIndex <= 0xffff);
390 clearBit(coreIndex * 2 + 1);
391}
392
393void QQmlData::flushPendingBinding(QObject *object, int coreIndex)
394{
395 QQmlData *data = QQmlData::get(object, false);
396 if (data && data->hasPendingBindingBit(coreIndex))
397 data->flushPendingBinding(coreIndex);
398}
399
401
402#endif // QQMLDATA_P_H
static bool(* isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int)
Definition qobject_p.h:69
static int(* receivers)(QAbstractDeclarativeData *, const QObject *, int)
Definition qobject_p.h:68
static void(* destroyed)(QAbstractDeclarativeData *, QObject *)
Definition qobject_p.h:66
static void(* signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **)
Definition qobject_p.h:67
\inmodule QtCore
Definition qhash.h:818
Definition qlist.h:74
\inmodule QtCore
Definition qhash.h:1348
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:153
\inmodule QtCore
Definition qobject.h:90
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
static void init()
Definition qqmldata_p.h:63
void setPendingBindingBit(QObject *obj, int)
Definition qqmldata_p.h:379
quint32 hasConstWrapper
Definition qqmldata_p.h:109
static void flushPendingBinding(QObject *object, int coreIndex)
Definition qqmldata_p.h:393
QV4::WeakValue jsWrapper
Definition qqmldata_p.h:193
static QQmlPropertyCache::ConstPtr ensurePropertyCache(QObject *object)
Definition qqmldata_p.h:252
QQmlNotifierEndpoint * notify(int index)
Definition qqmldata_p.h:321
bool hasExtendedData() const
Definition qqmldata_p.h:240
QVector< DeferredData * > deferredData
Definition qqmldata_p.h:187
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
Definition qqmldata_p.h:186
QQmlPropertyCache::ConstPtr propertyCache
Definition qqmldata_p.h:195
static QQmlData * get(const QObject *object)
Definition qqmldata_p.h:228
quint32 hasTaintedV4Object
Definition qqmldata_p.h:98
static bool keepAliveDuringGarbageCollection(const QObject *object)
Definition qqmldata_p.h:233
bool signalHasEndpoint(int index) const
Definition qqmldata_p.h:344
QQmlRefPointer< QQmlContextData > ownContext
Definition qqmldata_p.h:150
void clearBindingBit(int)
Definition qqmldata_p.h:364
quint32 hasVMEMetaObject
Definition qqmldata_p.h:107
bool hasPendingBindingBit(int index) const
Definition qqmldata_p.h:371
std::vector< QQmlPropertyObserver > propertyObservers
Definition qqmldata_p.h:154
quint32 explicitIndestructibleSet
Definition qqmldata_p.h:95
quint32 hasInterceptorMetaObject
Definition qqmldata_p.h:106
BindingBitsType * bindingBits
Definition qqmldata_p.h:122
quint32 bindingBitsArraySize
Definition qqmldata_p.h:115
void clearPendingBindingBit(int)
Definition qqmldata_p.h:386
static bool wasDeleted(const QObject *)
Definition qqmldata_p.h:312
static QQmlData * get(const QObjectPrivate *priv)
Definition qqmldata_p.h:214
void setBindingBit(QObject *obj, int)
Definition qqmldata_p.h:357
@ DoesNotOwnMemory
Definition qqmldata_p.h:58
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
quint32 dummy
Definition qqmldata_p.h:110
void setImplicitDestructible()
Definition qqmldata_p.h:81
quint32 isQueuedForDeletion
Definition qqmldata_p.h:99
static Q_ALWAYS_INLINE uint offsetForBit(int bit)
Definition qqmldata_p.h:260
quint32 rootObjectInCreation
Definition qqmldata_p.h:104
quint32 ownMemory
Definition qqmldata_p.h:87
quint32 indestructible
Definition qqmldata_p.h:92
quintptr BindingBitsType
Definition qqmldata_p.h:116
static QQmlData * get(QObject *object, bool create)
Definition qqmldata_p.h:224
static Q_ALWAYS_INLINE BindingBitsType bitFlagForBit(int bit)
Definition qqmldata_p.h:261
bool hasBindingBit(int) const
Definition qqmldata_p.h:349
NotifyList * notifyList
Definition qqmldata_p.h:138
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
static void * context
#define Q_UNLIKELY(x)
#define Q_NEVER_INLINE
#define Q_LIKELY(x)
#define Q_ALWAYS_INLINE
static QDBusError::ErrorType get(const char *name)
static const QMetaObjectPrivate * priv(const uint *data)
GLuint index
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLhandleARB obj
[2]
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
size_t quintptr
Definition qtypes.h:72
unsigned long long quint64
Definition qtypes.h:56
unsigned int uint
Definition qtypes.h:29
QVBoxLayout * layout
ba setBit(0, true)
view create()
QQmlRefPointer< QQmlContextData > context
Definition qqmldata_p.h:183
unsigned int deferredIdx
Definition qqmldata_p.h:176
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
Definition qqmldata_p.h:180
QMultiHash< int, const QV4::CompiledData::Binding * > bindings
Definition qqmldata_p.h:177
Q_DISABLE_COPY(DeferredData)
QQmlNotifierEndpoint ** notifies
Definition qqmldata_p.h:133
QQmlNotifierEndpoint * todo
Definition qqmldata_p.h:132