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
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// Qt-Security score:significant
4#ifndef QV4INTERNALCLASS_H
5#define QV4INTERNALCLASS_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 "qv4global_p.h"
19
20#include <QHash>
21#include <QVarLengthArray>
22#include <climits> // for UINT_MAX
23#include <private/qv4propertykey_p.h>
24#include <private/qv4heap_p.h>
25
27
28namespace QV4 {
29
30struct VTable;
31struct MarkStack;
32
34 uint index;
37 bool isValid() const { return !attributes.isEmpty(); }
38};
39
40struct PropertyHashData;
42{
48
50
51 inline PropertyHash();
52 inline PropertyHash(const PropertyHash &other);
53 inline ~PropertyHash();
54 PropertyHash &operator=(const PropertyHash &other);
55
56 void addEntry(const Entry &entry, int classSize);
57 Entry *lookup(PropertyKey identifier) const;
58 void detach(bool grow, int classSize);
59};
60
62{
63 PropertyHashData(int numBits);
65 free(entries);
66 }
67
69 int alloc;
70 int size;
73};
74
76{
77 d = new PropertyHashData(3);
78}
79
81{
82 d = other.d;
84}
85
87{
88 if (!--d->refCount)
89 delete d;
90}
91
93{
94 ++other.d->refCount;
95 if (!--d->refCount)
96 delete d;
97 d = other.d;
98 return *this;
99}
100
101
102
104{
105 Q_ASSERT(d->entries);
106
107 uint idx = identifier.id() % d->alloc;
108 while (1) {
109 if (d->entries[idx].identifier == identifier)
110 return d->entries + idx;
111 if (!d->entries[idx].identifier.isValid())
112 return nullptr;
113 ++idx;
114 idx %= d->alloc;
115 }
116}
117
118template<class T>
120
121template<>
124 : refcount(1),
125 m_alloc(0),
126 m_size(0),
127 m_data(nullptr),
129 { }
134
135 void grow();
136
138
139 uint alloc() const { return m_alloc; }
140 uint size() const { return m_size; }
141 void setSize(uint s) { m_size = s; }
142
145
146 void mark(MarkStack *) {}
147
148 int refcount = 1;
149private:
151 uint m_size;
152
153 enum {
157 };
158
159 static_assert(NumAttributesInPointer > 0);
160
163 }
164
167 m_data[i] = t;
168 else
169 m_inlineData[i] = t;
170 }
171
172 union {
175 };
177};
178
179template<>
181 SharedInternalClassDataPrivate(ExecutionEngine *e) : refcount(1), engine(e) {}
185
186 template<typename StringOrSymbol = Heap::StringOrSymbol>
187 void markIfNecessary(const PropertyKey &value);
188
189 void grow();
190 uint alloc() const;
191 uint size() const;
192 void setSize(uint s);
193
194 PropertyKey at(uint i) const;
195 void set(uint i, PropertyKey t);
196
197 void mark(MarkStack *s);
198
199 int refcount = 1;
200private:
201 ExecutionEngine *engine;
202 WriteBarrier::Pointer<Heap::MemberData> data;
203};
204
205template<typename StringOrSymbol>
207{
208 QV4::WriteBarrier::markCustom(engine, [&](QV4::MarkStack *stack) {
209 if constexpr (QV4::WriteBarrier::isInsertionBarrier) {
210 if (auto s = value.asStringOrSymbol<StringOrSymbol>())
211 s->mark(stack);
212 }
213 });
214}
215
216template <typename T>
220
221 inline SharedInternalClassData(ExecutionEngine *e) {
222 d = new Private(e);
223 }
224
226 : d(other.d)
227 {
228 ++d->refcount;
229 }
231 if (!--d->refcount)
232 delete d;
233 }
235 ++other.d->refcount;
236 if (!--d->refcount)
237 delete d;
238 d = other.d;
239 return *this;
240 }
241
242 void add(uint pos, T value) {
243 d->markIfNecessary(value);
244 if (pos < d->size()) {
245 Q_ASSERT(d->refcount > 1);
246 // need to detach
247 Private *dd = new Private(*d, pos, value);
248 --d->refcount;
249 d = dd;
250 return;
251 }
252 Q_ASSERT(pos == d->size());
253 if (pos == d->alloc())
254 d->grow();
255 if (pos >= d->alloc()) {
256 qBadAlloc();
257 } else {
258 d->setSize(d->size() + 1);
259 d->set(pos, value);
260 }
261 }
262
263 void set(uint pos, T value) {
264 Q_ASSERT(pos < d->size());
265 d->markIfNecessary(value);
266 if (d->refcount > 1) {
267 // need to detach
268 Private *dd = new Private(*d);
269 --d->refcount;
270 d = dd;
271 }
272 d->set(pos, value);
273 }
274
275 T at(uint i) const {
276 Q_ASSERT(i < d->size());
277 return d->at(i);
278 }
279 T operator[] (uint i) {
280 Q_ASSERT(i < d->size());
281 return d->at(i);
282 }
283
284 void mark(MarkStack *s) { d->mark(s); }
285};
286
288{
289 union {
292 Heap::Object *prototype;
293 };
295 int flags;
296 enum {
297 // range 0-0xff is reserved for attribute changes
306 };
307
308 bool operator==(const InternalClassTransition &other) const
309 { return id == other.id && flags == other.flags; }
310
311 bool operator<(const InternalClassTransition &other) const
312 { return flags < other.flags || (flags == other.flags && id < other.id); }
313};
314
315namespace Heap {
316
318 enum Flag {
320 Sealed = 1 << 1,
321 Frozen = 1 << 2,
322 UsedAsProto = 1 << 3,
323 Locked = 1 << 4,
324 };
326
327 ExecutionEngine *engine;
329 quintptr protoId; // unique across the engine, gets changed whenever the proto chain changes
330 Heap::Object *prototype;
332
333 PropertyHash propertyTable; // id to valueIndex
336
340
341 uint size;
344
345 bool isExtensible() const { return !(flags & NotExtensible); }
346 bool isSealed() const { return flags & Sealed; }
347 bool isFrozen() const { return flags & Frozen; }
348 bool isUsedAsProto() const { return flags & UsedAsProto; }
349 bool isLocked() const { return flags & Locked; }
350
351 void init(ExecutionEngine *engine);
352 void init(InternalClass *other);
353 void destroy();
354
355 Q_QML_EXPORT ReturnedValue keyAt(uint index) const;
358
359 static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry);
362 static void changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry = nullptr);
363 static void removeMember(QV4::Object *object, PropertyKey identifier);
365 {
366 Q_ASSERT(id.isStringOrSymbol());
367
369 if (e && e->index < size)
370 return e;
371
372 return nullptr;
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, e->setterIndex, a };
384 }
385
386 return { UINT_MAX, UINT_MAX, Attr_Invalid };
387 }
388
390 uint index;
392 bool isValid() const { return index != UINT_MAX; }
393 };
394
396 {
397 Q_ASSERT(id.isStringOrSymbol());
398
400 if (e && e->index < size) {
401 PropertyAttributes a = propertyData.at(e->index);
402 if (!a.isEmpty())
403 return { e->index, a };
404 }
405
406 return { UINT_MAX, Attr_Invalid };
407 }
408
410 {
411 Q_ASSERT(id.isStringOrSymbol());
412
414 if (e && e->index < size) {
415 PropertyAttributes a = propertyData.at(e->index);
416 if (!a.isEmpty()) {
417 if (a.isAccessor()) {
418 Q_ASSERT(e->setterIndex != UINT_MAX);
419 return { e->setterIndex, a };
420 }
421 return { e->index, a };
422 }
423 }
424
425 return { UINT_MAX, Attr_Invalid };
426 }
427
429 {
430 Q_ASSERT(id.isStringOrSymbol());
431
433 if (e && e->index < size) {
434 Q_ASSERT(!propertyData.at(e->index).isEmpty());
435 return e->index;
436 }
437
438 return UINT_MAX;
439 }
440
441 bool verifyIndex(const PropertyKey id, uint index)
442 {
443 Q_ASSERT(id.isStringOrSymbol());
444
446 if (e && e->index < size) {
447 Q_ASSERT(!propertyData.at(e->index).isEmpty());
448 return e->index == index;
449 }
450
451 return false;
452 }
453
456 Q_REQUIRED_RESULT InternalClass *canned(); // sealed + nonExtensible
457 Q_REQUIRED_RESULT InternalClass *cryopreserved(); // frozen + sealed + nonExtensible
458 bool isImplicitlyFrozen() const;
459
461
463 if (vtable == vt)
464 return this;
465 return changeVTableImpl(vt);
466 }
472
474
475 static void markObjects(Heap::Base *ic, MarkStack *stack);
476
477private:
480 InternalClass *addMemberImpl(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry);
481
482 void removeChildEntry(InternalClass *child);
483 friend struct ::QV4::ExecutionEngine;
484};
485
486inline
491
492}
493
494}
495
496QT_END_NAMESPACE
497
498#endif
ArrayElementLessThan(ExecutionEngine *engine, const Value &comparefn)
bool operator()(Value v1, Value v2) const
ReturnedValue operator*() const
Definition qv4value_p.h:477
OptionalReturnedValue(ReturnedValue v)
Definition qv4value_p.h:470
ReturnedValue operator->() const
Definition qv4value_p.h:476
DECLARE_HEAP_OBJECT(StrictArgumentsObject, Object)
DECLARE_EXPORTED_HEAP_OBJECT(Object, Base)
Definition qv4object_p.h:37
DECLARE_HEAP_OBJECT(ArgumentsObject, Object)
DECLARE_HEAP_OBJECT(MemberData, Base)
DECLARE_HEAP_OBJECT(ArrayData, Base)
Q_STATIC_ASSERT(std::is_trivial_v< ArrayData >)
CallResultDestination
Definition qjsvalue.h:23
Value Primitive
Definition qv4value_p.h:351
Scoped< FunctionObject > ScopedFunctionObject
void sortHelper(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
QVector< StackFrame > StackTrace
int qYouForgotTheQ_MANAGED_Macro(T, T)
bool hasExceptionOrIsInterrupted(ExecutionEngine *engine)
Scoped< Object > ScopedObject
ReturnedValue value_convert(ExecutionEngine *e, const Value &v)
Scoped< ArrayObject > ScopedArrayObject
Scoped< String > ScopedString
Scoped< StringOrSymbol > ScopedStringOrSymbol
void qYouForgotTheQ_MANAGED_Macro(T1, T2)
PropertyFlag
@ Attr_Invalid
@ Attr_NotConfigurable
@ Attr_Data
@ Attr_NotEnumerable
@ Attr_ReadOnly
@ Attr_NotWritable
@ Attr_ReadOnly_ButConfigurable
@ Attr_Accessor
CallData * callDatafromJS(const Scope &scope, const Args *args, const FunctionObject *f)
Definition qv4jscall_p.h:41
Q_STATIC_ASSERT(sizeof(CppStackFrame)==sizeof(JSTypesStackFrame))
Scoped< ExecutionContext > ScopedContext
Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_RELOCATABLE_TYPE)
DEFINE_OBJECT_VTABLE(StrictArgumentsObject)
DEFINE_OBJECT_VTABLE(ArgumentsObject)
#define V4_ARRAYDATA(DataClass)
#define V4_MANAGED(DataClass, superClass)
#define V4_MANAGED_SIZE_TEST
#define V4_NEEDS_DESTROY
#define V4_MANAGED_ITSELF(DataClass, superClass)
#define Q_MANAGED_TYPE(type)
#define V4_INTERNALCLASS(c)
#define Q_MANAGED_CHECK
static qint64 virtualGetLength(const Managed *m)
static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *desc, PropertyAttributes attrs)
Heap::CallContext * context() const
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
static OwnPropertyKeyIterator * virtualOwnPropertyKeys(const Object *m, Value *target)
static bool isNonStrictArgumentsObject(Managed *m)
static bool virtualDeleteProperty(Managed *m, PropertyKey id)
static PropertyAttributes virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p)
bool isMapped(uint arg) const
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
static qint64 virtualGetLength(const Managed *m)
QStringList toQStringList() const
void(* setAttribute)(Object *o, uint index, PropertyAttributes attrs)
bool(* putArray)(Object *o, uint index, const Value *values, uint n)
bool(* put)(Object *o, uint index, const Value &value)
void(* push_front)(Object *o, const Value *values, uint n)
ReturnedValue(* get)(const Heap::ArrayData *d, uint index)
bool(* del)(Object *o, uint index)
ReturnedValue(* pop_front)(Object *o)
static constexpr size_t offset
Definition qv4value_p.h:408
void set(EngineBase *e, HeapBasePtr b)
Definition qv4value_p.h:418
HeapBasePtr base()
Definition qv4value_p.h:409
void set(EngineBase *e, const Value &newVal)
Definition qv4value_p.h:415
void init(const QStringList &list)
void init(InternalClass *other)
IndexAndAttribute findValueOrSetter(const PropertyKey id)
void init(ExecutionEngine *engine)
static void addMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry)
InternalClassEntry find(const PropertyKey id)
bool verifyIndex(const PropertyKey id, uint index)
QVarLengthArray< Transition, 1 > transitions
SharedInternalClassData< PropertyKey > nameMap
IndexAndAttribute findValueOrGetter(const PropertyKey id)
InternalClassTransition Transition
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)
static void changeMember(QV4::Object *object, PropertyKey id, PropertyAttributes data, InternalClassEntry *entry=nullptr)
PropertyHash::Entry * findEntry(const PropertyKey id)
SharedInternalClassData< PropertyAttributes > propertyData
void init(double val)
PropertyAttributes attributes(uint i) const
uint mappedIndex(uint index) const
void setData(EngineBase *e, uint index, Value newVal)
const Value & data(uint index) const
uint mappedIndex(uint index) const
PropertyAttributes attributes(uint i) const
PropertyAttributes attributes
bool operator<(const InternalClassTransition &other) const
bool operator==(const InternalClassTransition &other) const
static Heap::MemberData * allocate(QV4::ExecutionEngine *e, uint n, Heap::MemberData *old=nullptr)
const Value * data() const
void set(EngineBase *e, uint index, Value v)
const Value & operator[](uint idx) const
void set(EngineBase *e, uint index, Heap::Base *b)
uint size() const
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
PropertyHash::Entry * entries
void addEntry(const Entry &entry, int classSize)
PropertyHash(const PropertyHash &other)
PropertyHashData * d
PropertyHash & operator=(const PropertyHash &other)
void detach(bool grow, int classSize)
Entry * lookup(PropertyKey identifier) const
const Value * operator->() const
bool isNull() const
const Value & operator*() const
void set(EngineBase *e, Value newVal)
bool isStringOrSymbol() const
bool isValid() const
bool isArrayIndex() const
static PropertyKey fromId(quint64 id)
Heap::StringOrSymbol * toStringOrSymbol(ExecutionEngine *e)
bool isCanonicalNumericIndexString() const
Q_QML_EXPORT bool isSymbol() const
bool operator<(const PropertyKey &other) const
Q_QML_EXPORT bool isString() const
StringOrSymbol * asStringOrSymbol() const
uint asArrayIndex() const
bool operator==(const PropertyKey &other) const
static PropertyKey invalid()
static PropertyKey fromStringOrSymbol(Engine *engine, StringOrSymbol *b)
friend size_t qHash(const PropertyKey &key, size_t seed=0)
static PropertyKey fromArrayIndex(uint idx)
Heap::String * asFunctionName(ExecutionEngine *e, FunctionNamePrefix prefix) const
quint64 id() const
bool operator!=(const PropertyKey &other) const
void setGetter(FunctionObject *g)
Heap::FunctionObject * getter() const
bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
void setSetter(FunctionObject *s)
void fullyPopulated(PropertyAttributes *attrs)
bool isCompatible(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
void copy(const Property *other, PropertyAttributes attrs)
void completed(PropertyAttributes *attrs)
Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter)
Heap::FunctionObject * setter() const
void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
Scope(const Managed *m)
Scope(ExecutionEngine *e)
Scope(ExecutionContext *ctx)
ScopedPropertyKey & operator=(const PropertyKey &other)
ScopedPropertyKey(const Scope &scope)
ScopedPropertyKey(const Scope &scope, const PropertyKey &v)
bool operator==(const PropertyKey &other) const
bool operator==(const ScopedPropertyKey &other) const
bool operator!=(const ScopedPropertyKey &other) const
bool operator!=(const PropertyKey &other) const
ScopedProperty(Scope &scope)
ScopedValue(const Scope &scope, Managed *m)
ScopedValue & operator=(Managed *m)
ScopedValue & operator=(const Value &v)
ScopedValue(const Scope &scope, const Value &v)
ScopedValue(ScopedValue &&)=default
ScopedValue(const Scope &scope)
ScopedValue(const ScopedValue &)=default
ScopedValue(const Scope &scope, const ReturnedValue &v)
ScopedValue & operator=(const ScopedValue &other)
const Value * operator->() const
ScopedValue(const Scope &scope, Heap::Base *o)
ScopedValue & operator=(const ReturnedValue &v)
ScopedValue & operator=(Heap::Base *o)
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)
SparseArrayNode * right
SparseArrayNode * left
SparseArrayNode * copy(SparseArray *d) const
SparseArrayNode * lowerBound(uint key)
const SparseArrayNode * previousNode() const
SparseArrayNode * parent() const
SparseArrayNode * nextNode()
SparseArrayNode * upperBound(uint key)
const SparseArrayNode * nextNode() const
SparseArrayNode * previousNode()
void setParent(SparseArrayNode *pp)
SparseArrayNode * upperBound(uint key)
SparseArrayNode * erase(SparseArrayNode *n)
void push_back(uint at, uint len)
SparseArrayNode * lowerBound(uint key)
const SparseArrayNode * begin() const
SparseArrayNode * insert(uint akey)
void push_front(uint at)
uint pop_back(uint len)
QList< int > keys() const
SparseArrayNode * findNode(uint akey) const
void freeTree(SparseArrayNode *root, int alignment)
const SparseArrayNode * end() const
uint nEntries() const
const Value * data() const
Definition qv4value_p.h:450
Value values[1]
Definition qv4value_p.h:431
void set(EngineBase *e, uint index, Value v)
Definition qv4value_p.h:440
void set(EngineBase *e, uint index, Value::HeapBasePtr b)
Definition qv4value_p.h:443
void mark(MarkStack *markStack)
Definition qv4value_p.h:454
Value::HeapBasePtr base()
Definition qv4value_p.h:433
const Value & operator[](uint index) const
Definition qv4value_p.h:446
static constexpr size_t offset
Definition qv4value_p.h:428