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
qjsvalue_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
4//
5// W A R N I N G
6// -------------
7//
8// This file is not part of the Qt API. It exists purely as an
9// implementation detail. This header file may change from version to
10// version without notice, or even be removed.
11//
12// We mean it.
13//
14
15#ifndef QJSVALUE_P_H
16#define QJSVALUE_P_H
17
18#include <qjsvalue.h>
19#include <private/qtqmlglobal_p.h>
20#include <private/qv4value_p.h>
21#include <private/qv4string_p.h>
22#include <private/qv4engine_p.h>
23#include <private/qv4mm_p.h>
24#include <private/qv4persistent_p.h>
25
26#include <QtCore/qthread.h>
27
29
31{
32 static constexpr quint64 s_tagBits = 3; // 3 bits mask
33 static constexpr quint64 s_tagMask = (1 << s_tagBits) - 1;
34
35 static constexpr quint64 s_pointerBit = 0x1;
36
37public:
38 enum class Kind {
39 Undefined = 0x0,
40 Null = 0x2,
41 IntValue = 0x4,
42 BoolValue = 0x6,
43 DoublePtr = 0x0 | s_pointerBit,
44 QV4ValuePtr = 0x2 | s_pointerBit,
45 QStringPtr = 0x4 | s_pointerBit,
46 };
47
48 static_assert(quint64(Kind::Undefined) <= s_tagMask);
49 static_assert(quint64(Kind::Null) <= s_tagMask);
50 static_assert(quint64(Kind::IntValue) <= s_tagMask);
51 static_assert(quint64(Kind::BoolValue) <= s_tagMask);
52 static_assert(quint64(Kind::DoublePtr) <= s_tagMask);
53 static_assert(quint64(Kind::QV4ValuePtr) <= s_tagMask);
54 static_assert(quint64(Kind::QStringPtr) <= s_tagMask);
55
56 static Kind tag(quint64 raw) { return Kind(raw & s_tagMask); }
57
58#if QT_POINTER_SIZE == 4
59 static void *pointer(quint64 raw)
60 {
61 Q_ASSERT(quint64(tag(raw)) & s_pointerBit);
62 return reinterpret_cast<void *>(raw >> 32);
63 }
64
65 static quint64 encodePointer(void *pointer, Kind tag)
66 {
67 Q_ASSERT(quint64(tag) & s_pointerBit);
68 return (quint64(quintptr(pointer)) << 32) | quint64(tag);
69 }
70#else
71 static constexpr quint64 s_minAlignment = 1 << s_tagBits;
72 static_assert(alignof(double) >= s_minAlignment);
73 static_assert(alignof(QV4::Value) >= s_minAlignment);
74 static_assert(alignof(QString) >= s_minAlignment);
75
76 static void *pointer(quint64 raw)
77 {
78 Q_ASSERT(quint64(tag(raw)) & s_pointerBit);
79 return reinterpret_cast<void *>(raw & ~s_tagMask);
80 }
81
83 {
84 Q_ASSERT(quint64(tag) & s_pointerBit);
85 return quintptr(pointer) | quint64(tag);
86 }
87#endif
88
90 {
92 }
93
95 {
96 return quint64(Kind::Null);
97 }
98
99 static int intValue(quint64 v)
100 {
102 return v >> 32;
103 }
104
106 {
107 return (quint64(intValue) << 32) | quint64(Kind::IntValue);
108 }
109
110 static quint64 encode(uint uintValue)
111 {
112 return (uintValue < uint(std::numeric_limits<int>::max()))
113 ? encode(int(uintValue))
114 : encode(double(uintValue));
115 }
116
117 static bool boolValue(quint64 v)
118 {
120 return v >> 32;
121 }
122
124 {
125 return (quint64(boolValue) << 32) | quint64(Kind::BoolValue);
126 }
127
128 static double *doublePtr(quint64 v)
129 {
131 return static_cast<double *>(pointer(v));
132 }
133
134 static quint64 encode(double doubleValue)
135 {
136 return encodePointer(new double(doubleValue), Kind::DoublePtr);
137 }
138
140 {
142 return static_cast<QV4::Value *>(pointer(v));
143 }
144
145 static quint64 encode(const QV4::Value &qv4Value)
146 {
147 switch (qv4Value.type()) {
149 return encode(qv4Value.booleanValue());
151 return encode(qv4Value.integerValue());
153 auto managed = qv4Value.as<QV4::Managed>();
154 auto engine = managed->engine();
155 auto mm = engine->memoryManager;
156 QV4::Value *m = mm->m_persistentValues->allocate();
157 Q_ASSERT(m);
158 // we create a new strong reference to the heap managed object
159 // to avoid having to rescan the persistent values, we mark it here
162 managed->heapObject()->mark(stack);
163 });
164 *m = qv4Value;
166 }
168 return encode(qv4Value.doubleValue());
170 return encodeNull();
172 Q_UNREACHABLE();
173 break;
175 break;
176 }
177
178 return encodeUndefined();
179 }
180
182 {
184 return static_cast<QString *>(pointer(v));
185 }
186
187 static quint64 encode(QString stringValue)
188 {
189 return encodePointer(new QString(std::move(stringValue)), Kind::QStringPtr);
190 }
191
192 static quint64 encode(QLatin1String stringValue)
193 {
194 return encodePointer(new QString(std::move(stringValue)), Kind::QStringPtr);
195 }
196
198 {
200 setValue(&result, d);
201 return result;
202 }
203
204 template<typename T>
205 static const T *asManagedType(const QJSValue *jsval)
206 {
207 if (tag(jsval->d) == Kind::QV4ValuePtr) {
208 if (const QV4::Value *value = qv4ValuePtr(jsval->d))
209 return value->as<T>();
210 }
211 return nullptr;
212 }
213
214 // This is a move operation and transfers ownership.
216 {
217 if (tag(jsval->d) == Kind::QV4ValuePtr) {
218 if (QV4::Value *value = qv4ValuePtr(jsval->d)) {
219 jsval->d = encodeUndefined();
220 return value;
221 }
222 }
223 return nullptr;
224 }
225
227 {
228 switch (tag(jsval->d)) {
229 case Kind::BoolValue:
230 return QV4::Encode(boolValue(jsval->d));
231 case Kind::IntValue:
232 return QV4::Encode(intValue(jsval->d));
233 case Kind::DoublePtr:
234 return QV4::Encode(*doublePtr(jsval->d));
235 case Kind::Null:
236 return QV4::Encode::null();
237 case Kind::Undefined:
239 case Kind::QStringPtr:
240 break;
241 }
242
243 return QV4::Encode::undefined();
244 }
245
246 // Beware: This only returns a non-null string if the QJSValue actually holds one.
247 // QV4::Strings are kept as managed values. Retrieve those with getValue().
248 static const QString *asQString(const QJSValue *jsval)
249 {
250 if (tag(jsval->d) == Kind::QStringPtr) {
251 if (const QString *string = qStringPtr(jsval->d))
252 return string;
253 }
254 return nullptr;
255 }
256
258 {
259 switch (tag(jsval->d)) {
260 case Kind::BoolValue:
261 return QV4::Encode(boolValue(jsval->d));
262 case Kind::IntValue:
263 return QV4::Encode(intValue(jsval->d));
264 case Kind::DoublePtr:
265 return QV4::Encode(*doublePtr(jsval->d));
266 case Kind::Null:
267 return QV4::Encode::null();
269 return qv4ValuePtr(jsval->d)->asReturnedValue();
270 case Kind::Undefined:
271 case Kind::QStringPtr:
272 break;
273 }
274
275 return QV4::Encode::undefined();
276 }
277
278 static void setString(QJSValue *jsval, QString s)
279 {
280 jsval->d = encode(std::move(s));
281 }
282
283 // Only use this with an existing persistent value.
284 // Ownership is transferred to the QJSValue.
286 {
287 jsval->d = encodePointer(v, Kind::QV4ValuePtr);
288 }
289
290 static void setValue(QJSValue *jsval, const QV4::Value &v)
291 {
292 jsval->d = encode(v);
293 }
294
295 // Moves any QString onto the V4 heap, changing the value to reflect that.
297 {
298 if (const QString *string = asQString(jsval)) {
299 jsval->d = encode(QV4::Value::fromHeapObject(e->newString(*string)));
300 delete string;
301 }
302 }
303
304 // Converts any QString on the fly, involving an allocation.
305 // Does not change the value.
307 const QJSValue &jsval)
308 {
309 if (const QString *string = asQString(&jsval))
310 return e->newString(*string)->asReturnedValue();
311 if (const QV4::Value *val = asManagedType<QV4::Managed>(&jsval)) {
313 return val->asReturnedValue();
314
315 qWarning("JSValue can't be reassigned to another engine.");
316 return QV4::Encode::undefined();
317 }
318 return asPrimitiveType(&jsval);
319 }
320
322 {
323 if (tag(jsval->d) == Kind::QV4ValuePtr) {
324 if (const QV4::Value *value = qv4ValuePtr(jsval->d))
326 }
327
328 return nullptr;
329 }
330
331 static bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval)
332 {
333 QV4::ExecutionEngine *v4 = engine(&jsval);
334 return !v4 || v4 == e;
335 }
336
337 static void free(QJSValue *jsval)
338 {
339 switch (tag(jsval->d)) {
340 case Kind::Undefined:
341 case Kind::Null:
342 case Kind::IntValue:
343 case Kind::BoolValue:
344 return;
345 case Kind::DoublePtr:
346 delete doublePtr(jsval->d);
347 return;
348 case Kind::QStringPtr:
349 delete qStringPtr(jsval->d);
350 return;
352 break;
353 }
354
355 // We need a mutable value for free(). It needs to write to the actual memory.
356 QV4::Value *m = qv4ValuePtr(jsval->d);
357 Q_ASSERT(m); // Otherwise it would have been undefined above.
359 if (QJSEngine *jsEngine = e->jsEngine()) {
360 if (jsEngine->thread() != QThread::currentThread()) {
362 jsEngine, [m](){ QV4::PersistentValueStorage::free(m); });
363 return;
364 }
365 }
366 }
368 }
369};
370
372
373#endif
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
QJSEngine * engine() const
Returns the QJSEngine this QJSManagedValue belongs to.
static quint64 encode(bool boolValue)
Definition qjsvalue_p.h:123
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
Definition qjsvalue_p.h:197
static void setString(QJSValue *jsval, QString s)
Definition qjsvalue_p.h:278
static bool boolValue(quint64 v)
Definition qjsvalue_p.h:117
static QV4::Value * qv4ValuePtr(quint64 v)
Definition qjsvalue_p.h:139
static int intValue(quint64 v)
Definition qjsvalue_p.h:99
static double * doublePtr(quint64 v)
Definition qjsvalue_p.h:128
static bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval)
Definition qjsvalue_p.h:331
static QV4::ExecutionEngine * engine(const QJSValue *jsval)
Definition qjsvalue_p.h:321
static quint64 encodePointer(void *pointer, Kind tag)
Definition qjsvalue_p.h:82
static QV4::Value * takeManagedValue(QJSValue *jsval)
Definition qjsvalue_p.h:215
static QV4::ReturnedValue asReturnedValue(const QJSValue *jsval)
Definition qjsvalue_p.h:257
static const QString * asQString(const QJSValue *jsval)
Definition qjsvalue_p.h:248
static quint64 encodeNull()
Definition qjsvalue_p.h:94
static constexpr quint64 s_minAlignment
Definition qjsvalue_p.h:71
static QString * qStringPtr(quint64 v)
Definition qjsvalue_p.h:181
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
Definition qjsvalue_p.h:306
static quint64 encode(const QV4::Value &qv4Value)
Definition qjsvalue_p.h:145
static void adoptPersistentValue(QJSValue *jsval, QV4::Value *v)
Definition qjsvalue_p.h:285
static QV4::ReturnedValue asPrimitiveType(const QJSValue *jsval)
Definition qjsvalue_p.h:226
static void setValue(QJSValue *jsval, const QV4::Value &v)
Definition qjsvalue_p.h:290
static void manageStringOnV4Heap(QV4::ExecutionEngine *e, QJSValue *jsval)
Definition qjsvalue_p.h:296
static quint64 encode(int intValue)
Definition qjsvalue_p.h:105
static const T * asManagedType(const QJSValue *jsval)
Definition qjsvalue_p.h:205
static quint64 encode(double doubleValue)
Definition qjsvalue_p.h:134
static void * pointer(quint64 raw)
Definition qjsvalue_p.h:76
static quint64 encode(QString stringValue)
Definition qjsvalue_p.h:187
static quint64 encodeUndefined()
Definition qjsvalue_p.h:89
static quint64 encode(QLatin1String stringValue)
Definition qjsvalue_p.h:192
static void free(QJSValue *jsval)
Definition qjsvalue_p.h:337
static quint64 encode(uint uintValue)
Definition qjsvalue_p.h:110
static Kind tag(quint64 raw)
Definition qjsvalue_p.h:56
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QThread * currentThread()
Definition qthread.cpp:1039
QJSManagedValue managed(std::move(val), &engine)
Combined button and popup list for selecting options.
quint64 ReturnedValue
AudioChannelLayoutTag tag
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLdouble s
[6]
Definition qopenglext.h:235
GLuint GLfloat * val
GLsizei const void * pointer
Definition qopenglext.h:384
GLuint64EXT * result
[6]
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
size_t quintptr
Definition qtypes.h:167
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
#define encode(x)
QJSEngine engine
[0]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
Heap::String * newString(char16_t c)
ReturnedValue asReturnedValue() const
Definition qv4value_p.h:342
static ExecutionEngine * getEngine(const Value *v)
static void free(Value *v)
static Value fromHeapObject(HeapBasePtr m)
Definition qv4value_p.h:84
static void markCustom(Engine *engine, F &&markFunction)
static constexpr bool isInsertionBarrier