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
qv4identifiertable.cpp
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
4#include "qv4symbol_p.h"
5#include <private/qv4identifierhashdata_p.h>
6#include <private/qprimefornumbits_p.h>
7
9
10namespace QV4 {
11
13 : engine(engine)
14 , size(0)
15 , numBits(numBits)
16{
20 memset(entriesByHash, 0, alloc*sizeof(Heap::String *));
21 memset(entriesById, 0, alloc*sizeof(Heap::String *));
22}
23
25{
26 free(entriesByHash);
27 free(entriesById);
28 for (const auto &h : std::as_const(idHashes))
29 h->identifierTable = nullptr;
30}
31
33{
34 uint hash = str->hashValue();
35
37 return;
38
40
41 bool grow = (alloc <= size*2);
42
43 if (grow) {
44 ++numBits;
45 int newAlloc = qPrimeForNumBits(numBits);
46 Heap::StringOrSymbol **newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
47 memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
48 for (uint i = 0; i < alloc; ++i) {
50 if (!e)
51 continue;
52 uint idx = e->stringHash % newAlloc;
53 while (newEntries[idx]) {
54 ++idx;
55 idx %= newAlloc;
56 }
57 newEntries[idx] = e;
58 }
59 free(entriesByHash);
60 entriesByHash = newEntries;
61
62 newEntries = (Heap::StringOrSymbol **)malloc(newAlloc*sizeof(Heap::String *));
63 memset(newEntries, 0, newAlloc*sizeof(Heap::StringOrSymbol *));
64 for (uint i = 0; i < alloc; ++i) {
66 if (!e)
67 continue;
68 uint idx = e->identifier.id() % newAlloc;
69 while (newEntries[idx]) {
70 ++idx;
71 idx %= newAlloc;
72 }
73 newEntries[idx] = e;
74 }
75 free(entriesById);
76 entriesById = newEntries;
77
78 alloc = newAlloc;
79 }
80
81 uint idx = hash % alloc;
82 while (entriesByHash[idx]) {
83 ++idx;
84 idx %= alloc;
85 }
86 entriesByHash[idx] = str;
87
88 idx = str->identifier.id() % alloc;
89 while (entriesById[idx]) {
90 ++idx;
91 idx %= alloc;
92 }
93 entriesById[idx] = str;
94
95 ++size;
96}
97
98
99
101{
102 uint subtype;
103 uint hash = String::createHashValue(s.constData(), s.size(), &subtype);
106 str->stringHash = hash;
107 str->subtype = subtype;
108 str->identifier = PropertyKey::fromArrayIndex(hash);
109 return str;
110 }
111 return resolveStringEntry(s, hash, subtype);
112}
113
114Heap::String *IdentifierTable::resolveStringEntry(const QString &s, uint hash, uint subtype)
115{
116 uint idx = hash % alloc;
117 while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
118 if (e->stringHash == hash && e->toQString() == s)
119 return static_cast<Heap::String *>(e);
120 ++idx;
121 idx %= alloc;
122 }
123
124 Heap::String *str = engine->newString(s);
125 str->stringHash = hash;
126 str->subtype = subtype;
127 addEntry(str);
128 return str;
129}
130
132{
133 Q_ASSERT(s.at(0) == QLatin1Char('@'));
134
135 uint subtype;
136 uint hash = String::createHashValue(s.constData(), s.size(), &subtype);
137 uint idx = hash % alloc;
138 while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
139 if (e->stringHash == hash && e->toQString() == s)
140 return static_cast<Heap::Symbol *>(e);
141 ++idx;
142 idx %= alloc;
143 }
144
146 str->stringHash = hash;
147 str->subtype = subtype;
148 addEntry(str);
149 return str;
150
151}
152
153
155{
156 if (str->identifier.isValid())
157 return str->identifier;
158 uint hash = str->hashValue();
160 str->identifier = PropertyKey::fromArrayIndex(hash);
161 return str->identifier;
162 }
163
164 uint idx = hash % alloc;
165 while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
166 if (e->stringHash == hash && e->toQString() == str->toQString()) {
167 str->identifier = e->identifier;
169 e->identifier.asStringOrSymbol()->mark(stack);
170 });
171 return e->identifier;
172 }
173 ++idx;
174 idx %= alloc;
175 }
176
177 addEntry(const_cast<QV4::Heap::String *>(str));
178 return str->identifier;
179}
180
182{
183 if (i.isArrayIndex())
184 return engine->newString(QString::number(i.asArrayIndex()));
185 if (!i.isValid())
186 return nullptr;
187
188 uint idx = i.id() % alloc;
189 while (1) {
191 if (!e || e->identifier == i)
192 return e;
193 ++idx;
194 idx %= alloc;
195 }
196}
197
199{
201 Q_ASSERT(s && s->internalClass->vtable->isString);
202 return static_cast<Heap::String *>(s);
203}
204
206{
208 Q_ASSERT(!s || !s->internalClass->vtable->isString);
209 return static_cast<Heap::Symbol *>(s);
210}
211
213{
214 for (const auto &h : idHashes)
215 h->markObjects(markStack);
216}
217
219{
220 int freed = 0;
221
222 Heap::StringOrSymbol **newTable = (Heap::StringOrSymbol **)malloc(alloc*sizeof(Heap::String *));
223 memset(newTable, 0, alloc*sizeof(Heap::StringOrSymbol *));
224 memset(entriesById, 0, alloc*sizeof(Heap::StringOrSymbol *));
225 for (uint i = 0; i < alloc; ++i) {
227 if (!e)
228 continue;
229 if (!e->isMarked()) {
230 ++freed;
231 continue;
232 }
233 uint idx = e->hashValue() % alloc;
234 while (newTable[idx]) {
235 ++idx;
236 if (idx == alloc)
237 idx = 0;
238 }
239 newTable[idx] = e;
240
241 idx = e->identifier.id() % alloc;
242 while (entriesById[idx]) {
243 ++idx;
244 if (idx == alloc)
245 idx = 0;
246 }
247 entriesById[idx] = e;
248 }
249 free(entriesByHash);
250 entriesByHash = newTable;
251
252 size -= freed;
253}
254
257{
258 uint subtype;
259 uint hash = String::createHashValue(s.constData(), s.size(), &subtype);
261 if (Q_UNLIKELY(conversionBehvior == ForceConversionToId))
262 hash = String::createHashValueDisallowingArrayIndex(s.constData(), s.size(), &subtype);
263 else
265 }
266 return resolveStringEntry(s, hash, subtype)->identifier;
267}
268
269}
270
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
QHash< int, QWidget * > hash
[35multi]
QString str
[2]
Combined button and popup list for selecting options.
#define Q_UNLIKELY(x)
static int grow(QLayoutStruct &ls, int delta)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLfloat GLfloat GLfloat GLfloat h
GLdouble s
[6]
Definition qopenglext.h:235
QT_BEGIN_NAMESPACE int qPrimeForNumBits(int numBits)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
unsigned int uint
Definition qtypes.h:34
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
Heap::String * newString(char16_t c)
bool isMarked() const
Definition qv4heap_p.h:68
unsigned hashValue() const
Definition qv4string_p.h:70
static void markObjects(Heap::Base *that, MarkStack *markStack)
Definition qv4string.cpp:14
Heap::Symbol * symbolForId(PropertyKey i) const
PropertyKey asPropertyKey(const Heap::String *str)
Heap::Symbol * insertSymbol(const QString &s)
Heap::StringOrSymbol ** entriesById
IdentifierTable(ExecutionEngine *engine, int numBits=8)
Heap::String * stringForId(PropertyKey i) const
Heap::String * insertString(const QString &s)
QSet< IdentifierHashData * > idHashes
void addEntry(Heap::StringOrSymbol *str)
Heap::StringOrSymbol ** entriesByHash
PropertyKey asPropertyKeyImpl(const Heap::String *str)
Heap::StringOrSymbol * resolveId(PropertyKey i) const
void markObjects(MarkStack *markStack)
static PropertyKey fromStringOrSymbol(Engine *engine, StringOrSymbol *b)
static PropertyKey fromArrayIndex(uint idx)
quint64 id() const
static uint createHashValueDisallowingArrayIndex(const QChar *ch, int length, uint *subtype)
static uint createHashValue(const QChar *ch, int length, uint *subtype)
static V4_NEEDS_DESTROY Heap::Symbol * create(ExecutionEngine *e, const QString &s)
static void markCustom(Engine *engine, F &&markFunction)