Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qv4internalclass_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#ifndef QV4INTERNALCLASS_H
4#define QV4INTERNALCLASS_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
19#include <QHash>
20#include <climits> // for UINT_MAX
21#include <private/qv4propertykey_p.h>
22#include <private/qv4heap_p.h>
23
25
26namespace QV4 {
27
28struct VTable;
29struct MarkStack;
30
35 bool isValid() const { return !attributes.isEmpty(); }
36};
37
38struct PropertyHashData;
40{
41 struct Entry {
45 };
46
48
49 inline PropertyHash();
50 inline PropertyHash(const PropertyHash &other);
51 inline ~PropertyHash();
53
54 void addEntry(const Entry &entry, int classSize);
55 Entry *lookup(PropertyKey identifier) const;
56 void detach(bool grow, int classSize);
57};
58
60{
63 free(entries);
64 }
65
67 int alloc;
68 int size;
71};
72
74{
75 d = new PropertyHashData(3);
76}
77
79{
80 d = other.d;
81 ++d->refCount;
82}
83
85{
86 if (!--d->refCount)
87 delete d;
88}
89
91{
92 ++other.d->refCount;
93 if (!--d->refCount)
94 delete d;
95 d = other.d;
96 return *this;
97}
98
99
100
102{
104
105 uint idx = identifier.id() % d->alloc;
106 while (1) {
107 if (d->entries[idx].identifier == identifier)
108 return d->entries + idx;
109 if (!d->entries[idx].identifier.isValid())
110 return nullptr;
111 ++idx;
112 idx %= d->alloc;
113 }
114}
115
116template<class T>
118
119template<>
122 : refcount(1),
123 m_alloc(0),
124 m_size(0),
126 m_engine(engine)
127 { }
132
133 void grow();
134
135 uint alloc() const { return m_alloc; }
136 uint size() const { return m_size; }
137 void setSize(uint s) { m_size = s; }
138
139 PropertyAttributes at(uint i) const { Q_ASSERT(i < m_alloc); return data(i); }
140 void set(uint i, PropertyAttributes t) { Q_ASSERT(i < m_alloc); setData(i, t); }
141
142 void mark(MarkStack *) {}
143
144 int refcount = 1;
145private:
146 uint m_alloc;
147 uint m_size;
148
149 enum {
150 SizeOfAttributesPointer = sizeof(PropertyAttributes *),
151 SizeOfAttributes = sizeof(PropertyAttributes),
152 NumAttributesInPointer = SizeOfAttributesPointer / SizeOfAttributes,
153 };
154
155 static_assert(NumAttributesInPointer > 0);
156
158 return m_alloc > NumAttributesInPointer ? m_data[i] : m_inlineData[i];
159 }
160
161 void setData(uint i, PropertyAttributes t) {
162 if (m_alloc > NumAttributesInPointer)
163 m_data[i] = t;
164 else
165 m_inlineData[i] = t;
166 }
167
168 union {
170 PropertyAttributes m_inlineData[NumAttributesInPointer];
171 };
172 ExecutionEngine *m_engine;
173};
174
175template<>
181
182 void grow();
183 uint alloc() const;
184 uint size() const;
185 void setSize(uint s);
186
187 PropertyKey at(uint i) const;
188 void set(uint i, PropertyKey t);
189
190 void mark(MarkStack *s);
191
192 int refcount = 1;
193private:
195 Heap::MemberData *data;
196};
197
198template <typename T>
202
204 d = new Private(e);
205 }
206
208 : d(other.d)
209 {
210 ++d->refcount;
211 }
213 if (!--d->refcount)
214 delete d;
215 }
217 ++other.d->refcount;
218 if (!--d->refcount)
219 delete d;
220 d = other.d;
221 return *this;
222 }
223
224 void add(uint pos, T value) {
225 if (pos < d->size()) {
226 Q_ASSERT(d->refcount > 1);
227 // need to detach
228 Private *dd = new Private(*d, pos, value);
229 --d->refcount;
230 d = dd;
231 return;
232 }
233 Q_ASSERT(pos == d->size());
234 if (pos == d->alloc())
235 d->grow();
236 if (pos >= d->alloc()) {
237 qBadAlloc();
238 } else {
239 d->setSize(d->size() + 1);
240 d->set(pos, value);
241 }
242 }
243
244 void set(uint pos, T value) {
245 Q_ASSERT(pos < d->size());
246 if (d->refcount > 1) {
247 // need to detach
248 Private *dd = new Private(*d);
249 --d->refcount;
250 d = dd;
251 }
252 d->set(pos, value);
253 }
254
255 T at(uint i) const {
256 Q_ASSERT(i < d->size());
257 return d->at(i);
258 }
260 Q_ASSERT(i < d->size());
261 return d->at(i);
262 }
263
264 void mark(MarkStack *s) { d->mark(s); }
265};
266
268{
269 union {
272 Heap::Object *prototype;
273 };
275 int flags;
276 enum {
277 // range 0-0xff is reserved for attribute changes
286 };
287
289 { return id == other.id && flags == other.flags; }
290
292 { return flags < other.flags || (flags == other.flags && id < other.id); }
293};
294
295namespace Heap {
296
298 enum Flag {
300 Sealed = 1 << 1,
301 Frozen = 1 << 2,
302 UsedAsProto = 1 << 3,
303 Locked = 1 << 4,
304 };
306
309 quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
310 Heap::Object *prototype;
312
313 PropertyHash propertyTable; // id to valueIndex
316
318 std::vector<Transition> transitions;
320
324
325 bool isExtensible() const { return !(flags & NotExtensible); }
326 bool isSealed() const { return flags & Sealed; }
327 bool isFrozen() const { return flags & Frozen; }
328 bool isUsedAsProto() const { return flags & UsedAsProto; }
329 bool isLocked() const { return flags & Locked; }
330
332 void init(InternalClass *other);
333 void destroy();
334
335 Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const;
338
343 static void removeMember(QV4::Object *object, PropertyKey identifier);
345 {
346 Q_ASSERT(id.isStringOrSymbol());
347
349 if (e && e->index < size)
350 return e;
351
352 return nullptr;
353 }
354
356 {
357 Q_ASSERT(id.isStringOrSymbol());
358
360 if (e && e->index < size) {
361 PropertyAttributes a = propertyData.at(e->index);
362 if (!a.isEmpty())
363 return { e->index, e->setterIndex, a };
364 }
365
366 return { UINT_MAX, UINT_MAX, Attr_Invalid };
367 }
368
372 bool isValid() const { return index != UINT_MAX; }
373 };
374
376 {
377 Q_ASSERT(id.isStringOrSymbol());
378
380 if (e && e->index < size) {
381 PropertyAttributes a = propertyData.at(e->index);
382 if (!a.isEmpty())
383 return { e->index, a };
384 }
385
386 return { UINT_MAX, Attr_Invalid };
387 }
388
390 {
391 Q_ASSERT(id.isStringOrSymbol());
392
394 if (e && e->index < size) {
395 PropertyAttributes a = propertyData.at(e->index);
396 if (!a.isEmpty()) {
397 if (a.isAccessor()) {
398 Q_ASSERT(e->setterIndex != UINT_MAX);
399 return { e->setterIndex, a };
400 }
401 return { e->index, a };
402 }
403 }
404
405 return { UINT_MAX, Attr_Invalid };
406 }
407
409 {
410 Q_ASSERT(id.isStringOrSymbol());
411
413 if (e && e->index < size) {
414 Q_ASSERT(!propertyData.at(e->index).isEmpty());
415 return e->index;
416 }
417
418 return UINT_MAX;
419 }
420
422 {
423 Q_ASSERT(id.isStringOrSymbol());
424
426 if (e && e->index < size) {
427 Q_ASSERT(!propertyData.at(e->index).isEmpty());
428 return e->index == index;
429 }
430
431 return false;
432 }
433
436 Q_REQUIRED_RESULT InternalClass *canned(); // sealed + nonExtensible
437 Q_REQUIRED_RESULT InternalClass *cryopreserved(); // frozen + sealed + nonExtensible
438 bool isImplicitlyFrozen() const;
439
441
443 if (vtable == vt)
444 return this;
445 return changeVTableImpl(vt);
446 }
448 if (prototype == proto)
449 return this;
450 return changePrototypeImpl(proto);
451 }
452
453 void updateProtoUsage(Heap::Object *o);
454
455 static void markObjects(Heap::Base *ic, MarkStack *stack);
456
457private:
458 Q_QML_EXPORT InternalClass *changeVTableImpl(const VTable *vt);
459 Q_QML_EXPORT InternalClass *changePrototypeImpl(Heap::Object *proto);
461
462 void removeChildEntry(InternalClass *child);
463 friend struct ::QV4::ExecutionEngine;
464};
465
466inline
468{
469 b->internalClass->mark(stack);
470}
471
472}
473
474}
475
477
478#endif
NSData * m_data
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
double e
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
@ Attr_Invalid
void qBadAlloc()
Definition qassert.cpp:131
#define Q_REQUIRED_RESULT
static int grow(QLayoutStruct &ls, int delta)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint entry
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble s
[6]
Definition qopenglext.h:235
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
size_t quintptr
Definition qtypes.h:72
unsigned int uint
Definition qtypes.h:29
unsigned char quint8
Definition qtypes.h:41
QFuture< QSet< QChar > > set
[10]
mimeData setData("text/csv", csvData)
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QLayoutItem * child
[0]
QAction * at
QJSEngine engine
[0]
static void markObjects(Base *, MarkStack *)
Q_REQUIRED_RESULT InternalClass * locked()
Q_REQUIRED_RESULT InternalClass * cryopreserved()
IndexAndAttribute findValueOrSetter(const PropertyKey id)
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
Q_REQUIRED_RESULT InternalClass * sealed()
InternalClassEntry find(const PropertyKey id)
bool verifyIndex(const PropertyKey id, uint index)
SharedInternalClassData< PropertyKey > nameMap
Q_REQUIRED_RESULT InternalClass * nonExtensible()
IndexAndAttribute findValueOrGetter(const PropertyKey id)
Q_REQUIRED_RESULT InternalClass * changePrototype(Heap::Object *proto)
Q_REQUIRED_RESULT InternalClass * frozen()
Q_REQUIRED_RESULT InternalClass * canned()
Q_REQUIRED_RESULT InternalClass * changeVTable(const VTable *vt)
InternalClassTransition Transition
Q_REQUIRED_RESULT InternalClass * asProtoClass()
Q_REQUIRED_RESULT InternalClass * changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry=nullptr)
uint indexOfValueOrGetter(const PropertyKey id)
Q_QML_PRIVATE_EXPORT QString keyAt(uint index) const
std::vector< Transition > transitions
InternalClassTransition & lookupOrInsertTransition(const InternalClassTransition &t)
static void markObjects(Heap::Base *ic, MarkStack *stack)
static void removeMember(QV4::Object *object, PropertyKey identifier)
void updateProtoUsage(Heap::Object *o)
PropertyHash::Entry * findEntry(const PropertyKey id)
SharedInternalClassData< PropertyAttributes > propertyData
PropertyAttributes attributes
bool operator<(const InternalClassTransition &other) const
bool operator==(const InternalClassTransition &other) const
PropertyHash::Entry * entries
void addEntry(const Entry &entry, int classSize)
PropertyHashData * d
PropertyHash & operator=(const PropertyHash &other)
void detach(bool grow, int classSize)
Entry * lookup(PropertyKey identifier) const
bool isValid() const
quint64 id() const
SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, PropertyKey value)
SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other)
void set(uint pos, T value)
SharedInternalClassData(ExecutionEngine *e)
void add(uint pos, T value)
SharedInternalClassData & operator=(const SharedInternalClassData &other)
SharedInternalClassDataPrivate< T > Private
SharedInternalClassData(const SharedInternalClassData &other)