Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4heap_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// Qt-Security score:critical reason:low-level-memory-management
4#ifndef QV4HEAP_P_H
5#define QV4HEAP_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/qv4global_p.h>
19#include <private/qv4mmdefs_p.h>
20#include <private/qv4writebarrier_p.h>
21#include <private/qv4vtable_p.h>
22#include <QtCore/QSharedPointer>
23
24// To check if Heap::Base::init is called (meaning, all subclasses did their init and called their
25// parent's init all up the inheritance chain), define QML_CHECK_INIT_DESTROY_CALLS below.
26#undef QML_CHECK_INIT_DESTROY_CALLS
27
28QT_BEGIN_NAMESPACE
29
30namespace QV4 {
31
32namespace Heap {
33
34template <typename T, size_t o>
35struct Pointer {
36 static constexpr size_t offset = o;
37 T operator->() const { return get(); }
38 operator T () const { return get(); }
39
41
42 void set(EngineBase *e, T newVal) {
43 WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Base *>(newVal));
44 }
45
46 T get() const { return reinterpret_cast<T>(ptr); }
47
48 template <typename Type>
49 Type *cast() { return static_cast<Type *>(ptr); }
50
51 Base *heapObject() const { return ptr; }
52
53private:
54 Base *ptr;
55};
56typedef Pointer<char *, 0> V4PointerCheck;
58
59struct Q_QML_EXPORT Base {
60 void *operator new(size_t) = delete;
61
62 static void markObjects(Base *, MarkStack *);
63
65
66 inline ReturnedValue asReturnedValue() const;
67 inline void mark(QV4::MarkStack *markStack);
68
69 inline bool isMarked() const {
70 const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
71 Chunk *c = h->chunk();
73 return Chunk::testBit(c->blackBitmap, h - c->realBase());
74 }
75 inline void setMarkBit() {
76 const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
77 Chunk *c = h->chunk();
79 return Chunk::setBit(c->blackBitmap, h - c->realBase());
80 }
81
82 inline bool inUse() const {
83 const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
84 Chunk *c = h->chunk();
86 return Chunk::testBit(c->objectBitmap, h - c->realBase());
87 }
88
89 void *operator new(size_t, Managed *m) { return m; }
90 void *operator new(size_t, Base *m) { return m; }
91 void operator delete(void *, Base *) {}
92
93 void init() { _setInitialized(); }
94 void destroy() { _setDestroyed(); }
95#ifdef QML_CHECK_INIT_DESTROY_CALLS
97 void _checkIsInitialized() {
99 fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n",
100 vtable()->className);
101 else if (_livenessStatus == Destroyed)
102 fprintf(stderr, "ERROR: use of object '%s' after call to destroy() !!\n",
103 vtable()->className);
105 }
106 void _checkIsDestroyed() {
108 fprintf(stderr, "ERROR: object '%s' was never destroyed completely !!\n",
109 vtable()->className);
111 }
113 void _setDestroyed() {
115 fprintf(stderr, "ERROR: attempting to destroy an uninitialized object '%s' !!\n",
116 vtable()->className);
117 else if (_livenessStatus == Destroyed)
118 fprintf(stderr, "ERROR: attempting to destroy repeatedly object '%s' !!\n",
119 vtable()->className);
122 }
123#else
128#endif
129};
131// This class needs to consist only of pointer sized members to allow
132// for a size/offset translation when cross-compiling between 32- and
133// 64-bit.
135Q_STATIC_ASSERT(offsetof(Base, internalClass) == 0);
137
138inline
140{
141 Q_ASSERT(inUse());
142 const HeapItem *h = reinterpret_cast<const HeapItem *>(this);
143 Chunk *c = h->chunk();
144 size_t index = h - c->realBase();
148 if (!(*bitmap & bit)) {
149 *bitmap |= bit;
150 markStack->push(this);
151 }
152}
153
154template<typename T, size_t o>
155Base *Pointer<T, o>::base() {
156 Base *base = reinterpret_cast<Base *>(this) - (offset/sizeof(Base *));
157 Q_ASSERT(base->inUse());
158 return base;
159}
160
161}
162
163#ifdef QT_NO_QOBJECT
164template <class T>
165struct QV4QPointer {
166};
167#else
168template <class T>
170 void init()
171 {
172 d = nullptr;
173 qObject = nullptr;
174 }
175
176 void init(T *o)
177 {
178 Q_ASSERT(d == nullptr);
179 Q_ASSERT(qObject == nullptr);
180 if (o) {
181 d = QtSharedPointer::ExternalRefCountData::getAndRef(o);
182 qObject = o;
183 }
184 }
185
186 void destroy()
187 {
188 if (d && !d->weakref.deref())
189 delete d;
190 d = nullptr;
191 qObject = nullptr;
192 }
193
194 T *data() const {
195 return d == nullptr || d->strongref.loadRelaxed() == 0 ? nullptr : qObject;
196 }
197 operator T*() const { return data(); }
198 inline T* operator->() const { return data(); }
200 {
201 if (d)
202 destroy();
203 init(o);
204 return *this;
205 }
206
207 bool isNull() const noexcept
208 {
209 return !isValid() || d->strongref.loadRelaxed() == 0;
210 }
211
212 bool isValid() const noexcept
213 {
214 return d != nullptr && qObject != nullptr;
215 }
216
217private:
218 QtSharedPointer::ExternalRefCountData *d;
219 T *qObject;
220};
222#endif
223
224}
225
226QT_END_NAMESPACE
227
228#endif
Pointer< char *, 0 > V4PointerCheck
Definition qv4heap_p.h:56
Q_STATIC_ASSERT(std::is_trivial_v< ArrayData >)
Definition qjsvalue.h:24
Base * heapObject() const
Definition qv4heap_p.h:51
void set(EngineBase *e, T newVal)
Definition qv4heap_p.h:42
T operator->() const
Definition qv4heap_p.h:37
static constexpr size_t offset
Definition qv4heap_p.h:36
bool isValid() const noexcept
Definition qv4heap_p.h:212
void init(T *o)
Definition qv4heap_p.h:176
T * data() const
Definition qv4heap_p.h:194
T * operator->() const
Definition qv4heap_p.h:198
operator T*() const
Definition qv4heap_p.h:197
bool isNull() const noexcept
Definition qv4heap_p.h:207
QV4QPointer & operator=(T *o)
Definition qv4heap_p.h:199