Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 <QVarLengthArray>
21#include <climits> // for UINT_MAX
22#include <private/qv4propertykey_p.h>
23#include <private/qv4heap_p.h>
24
26
27namespace QV4 {
28
29struct VTable;
30struct MarkStack;
31
38
39struct PropertyHashData;
41{
47
49
50 inline PropertyHash();
51 inline PropertyHash(const PropertyHash &other);
52 inline ~PropertyHash();
54
55 void addEntry(const Entry &entry, int classSize);
56 Entry *lookup(PropertyKey identifier) const;
57 void detach(bool grow, int classSize);
58};
59
73
75{
76 d = new PropertyHashData(3);
77}
78
80{
81 d = other.d;
82 ++d->refCount;
83}
84
86{
87 if (!--d->refCount)
88 delete d;
89}
90
92{
93 ++other.d->refCount;
94 if (!--d->refCount)
95 delete d;
96 d = other.d;
97 return *this;
98}
99
100
101
103{
105
106 uint idx = identifier.id() % d->alloc;
107 while (1) {
108 if (d->entries[idx].identifier == identifier)
109 return d->entries + idx;
110 if (!d->entries[idx].identifier.isValid())
111 return nullptr;
112 ++idx;
113 idx %= d->alloc;
114 }
115}
116
117template<class T>
119
120template<>
123 : refcount(1),
124 m_alloc(0),
125 m_size(0),
127 m_engine(engine)
128 { }
129 SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyAttributes> &other);
130 SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate<PropertyAttributes> &other,
133
134 void grow();
135
137
138 uint alloc() const { return m_alloc; }
139 uint size() const { return m_size; }
140 void setSize(uint s) { m_size = s; }
141
142 PropertyAttributes at(uint i) const { Q_ASSERT(i < m_alloc); return data(i); }
143 void set(uint i, PropertyAttributes t) { Q_ASSERT(i < m_alloc); setData(i, t); }
144
145 void mark(MarkStack *) {}
146
147 int refcount = 1;
148private:
149 uint m_alloc;
150 uint m_size;
151
152 enum {
153 SizeOfAttributesPointer = sizeof(PropertyAttributes *),
154 SizeOfAttributes = sizeof(PropertyAttributes),
155 NumAttributesInPointer = SizeOfAttributesPointer / SizeOfAttributes,
156 };
157
158 static_assert(NumAttributesInPointer > 0);
159
161 return m_alloc > NumAttributesInPointer ? m_data[i] : m_inlineData[i];
162 }
163
164 void setData(uint i, PropertyAttributes t) {
165 if (m_alloc > NumAttributesInPointer)
166 m_data[i] = t;
167 else
168 m_inlineData[i] = t;
169 }
170
171 union {
173 PropertyAttributes m_inlineData[NumAttributesInPointer];
174 };
175 ExecutionEngine *m_engine;
176};
177
178template<>
184
185 template<typename StringOrSymbol = Heap::StringOrSymbol>
186 void markIfNecessary(const PropertyKey &value);
187
188 void grow();
189 uint alloc() const;
190 uint size() const;
191 void setSize(uint s);
192
193 PropertyKey at(uint i) const;
194 void set(uint i, PropertyKey t);
195
196 void mark(MarkStack *s);
197
198 int refcount = 1;
199private:
202};
203
204template<typename StringOrSymbol>
206{
209 if (auto s = value.asStringOrSymbol<StringOrSymbol>())
210 s->mark(stack);
211 }
212 });
213}
214
215template <typename T>
217 using Private = SharedInternalClassDataPrivate<T>;
219
221 d = new Private(e);
222 }
223
225 : d(other.d)
226 {
227 ++d->refcount;
228 }
230 if (!--d->refcount)
231 delete d;
232 }
234 ++other.d->refcount;
235 if (!--d->refcount)
236 delete d;
237 d = other.d;
238 return *this;
239 }
240
241 void add(uint pos, T value) {
242 d->markIfNecessary(value);
243 if (pos < d->size()) {
244 Q_ASSERT(d->refcount > 1);
245 // need to detach
246 Private *dd = new Private(*d, pos, value);
247 --d->refcount;
248 d = dd;
249 return;
250 }
251 Q_ASSERT(pos == d->size());
252 if (pos == d->alloc())
253 d->grow();
254 if (pos >= d->alloc()) {
255 qBadAlloc();
256 } else {
257 d->setSize(d->size() + 1);
258 d->set(pos, value);
259 }
260 }
261
262 void set(uint pos, T value) {
263 Q_ASSERT(pos < d->size());
264 d->markIfNecessary(value);
265 if (d->refcount > 1) {
266 // need to detach
267 Private *dd = new Private(*d);
268 --d->refcount;
269 d = dd;
270 }
271 d->set(pos, value);
272 }
273
274 T at(uint i) const {
275 Q_ASSERT(i < d->size());
276 return d->at(i);
277 }
279 Q_ASSERT(i < d->size());
280 return d->at(i);
281 }
282
283 void mark(MarkStack *s) { d->mark(s); }
284};
285
287{
288 union {
291 Heap::Object *prototype;
292 };
294 int flags;
295 enum {
296 // range 0-0xff is reserved for attribute changes
305 };
306
308 { return id == other.id && flags == other.flags; }
309
311 { return flags < other.flags || (flags == other.flags && id < other.id); }
312};
313
314namespace Heap {
315
317 enum Flag {
319 Sealed = 1 << 1,
320 Frozen = 1 << 2,
321 UsedAsProto = 1 << 3,
322 Locked = 1 << 4,
323 };
325
328 quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
329 Heap::Object *prototype;
331
332 PropertyHash propertyTable; // id to valueIndex
333 SharedInternalClassData<PropertyKey> nameMap;
334 SharedInternalClassData<PropertyAttributes> propertyData;
335
337 QVarLengthArray<Transition, 1> transitions;
339
343
344 bool isExtensible() const { return !(flags & NotExtensible); }
345 bool isSealed() const { return flags & Sealed; }
346 bool isFrozen() const { return flags & Frozen; }
347 bool isUsedAsProto() const { return flags & UsedAsProto; }
348 bool isLocked() const { return flags & Locked; }
349
351 void init(InternalClass *other);
352 void destroy();
353
354 Q_QML_EXPORT ReturnedValue keyAt(uint index) const;
357
362 static void removeMember(QV4::Object *object, PropertyKey identifier);
364 {
365 Q_ASSERT(id.isStringOrSymbol());
366
368 if (e && e->index < size)
369 return e;
370
371 return nullptr;
372 }
373
375 {
376 Q_ASSERT(id.isStringOrSymbol());
377
379 if (e && e->index < size) {
381 if (!a.isEmpty())
382 return { e->index, e->setterIndex, a };
383 }
384
385 return { UINT_MAX, UINT_MAX, Attr_Invalid };
386 }
387
391 bool isValid() const { return index != UINT_MAX; }
392 };
393
395 {
396 Q_ASSERT(id.isStringOrSymbol());
397
399 if (e && e->index < size) {
401 if (!a.isEmpty())
402 return { e->index, a };
403 }
404
405 return { UINT_MAX, Attr_Invalid };
406 }
407
409 {
410 Q_ASSERT(id.isStringOrSymbol());
411
413 if (e && e->index < size) {
415 if (!a.isEmpty()) {
416 if (a.isAccessor()) {
417 Q_ASSERT(e->setterIndex != UINT_MAX);
418 return { e->setterIndex, a };
419 }
420 return { e->index, a };
421 }
422 }
423
424 return { UINT_MAX, Attr_Invalid };
425 }
426
428 {
429 Q_ASSERT(id.isStringOrSymbol());
430
432 if (e && e->index < size) {
433 Q_ASSERT(!propertyData.at(e->index).isEmpty());
434 return e->index;
435 }
436
437 return UINT_MAX;
438 }
439
441 {
442 Q_ASSERT(id.isStringOrSymbol());
443
445 if (e && e->index < size) {
446 Q_ASSERT(!propertyData.at(e->index).isEmpty());
447 return e->index == index;
448 }
449
450 return false;
451 }
452
455 Q_REQUIRED_RESULT InternalClass *canned(); // sealed + nonExtensible
456 Q_REQUIRED_RESULT InternalClass *cryopreserved(); // frozen + sealed + nonExtensible
457 bool isImplicitlyFrozen() const;
458
460
462 if (vtable == vt)
463 return this;
464 return changeVTableImpl(vt);
465 }
467 if (prototype == proto)
468 return this;
469 return changePrototypeImpl(proto);
470 }
471
472 void updateProtoUsage(Heap::Object *o);
473
474 static void markObjects(Heap::Base *ic, MarkStack *stack);
475
476private:
477 Q_QML_EXPORT InternalClass *changeVTableImpl(const VTable *vt);
478 Q_QML_EXPORT InternalClass *changePrototypeImpl(Heap::Object *proto);
480
481 void removeChildEntry(InternalClass *child);
482 friend struct ::QV4::ExecutionEngine;
483};
484
485inline
487{
488 b->internalClass->mark(stack);
489}
490
491}
492
493}
494
496
497#endif
NSData * m_data
Combined button and popup list for selecting options.
quint64 ReturnedValue
@ Attr_Invalid
void qBadAlloc()
Definition qassert.cpp:168
#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]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLbitfield flags
GLdouble s
[6]
Definition qopenglext.h:235
GLuint entry
GLdouble GLdouble t
Definition qopenglext.h:243
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
size_t quintptr
Definition qtypes.h:167
unsigned int uint
Definition qtypes.h:34
unsigned char quint8
Definition qtypes.h:46
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)
QVarLengthArray< Transition, 1 > transitions
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)
Q_QML_EXPORT ReturnedValue keyAt(uint index) const
InternalClassTransition Transition
Q_REQUIRED_RESULT InternalClass * asProtoClass()
Q_REQUIRED_RESULT InternalClass * changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry=nullptr)
uint indexOfValueOrGetter(const PropertyKey id)
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)
static void markCustom(Engine *engine, F &&markFunction)
static constexpr bool isInsertionBarrier