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
qv4value_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 QV4VALUE_P_H
4#define QV4VALUE_P_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 <limits.h>
18#include <cmath>
19
20#include <QtCore/QString>
21#include "qv4global_p.h"
22#include <private/qv4heap_p.h>
23#include <private/qv4internalclass_p.h>
24#include <private/qv4staticvalue_p.h>
25
26#include <private/qnumeric_p.h>
27#include <private/qv4calldata_p.h>
28
30
31namespace QV4 {
32
33namespace Heap {
34 struct Base;
35}
36
37struct Q_QML_EXPORT Value : public StaticValue
38{
40
41 Value() = default;
42 constexpr Value(quint64 val) : StaticValue(val) {}
43
44 static constexpr Value fromStaticValue(StaticValue staticValue)
45 {
46 return {staticValue._val};
47 }
48
49 inline bool isString() const;
50 inline bool isStringOrSymbol() const;
51 inline bool isSymbol() const;
52 inline bool isObject() const;
53 inline bool isFunctionObject() const;
54
56 if (!isString())
57 return nullptr;
58 return reinterpret_cast<String *>(const_cast<Value *>(this));
59 }
61 if (!isStringOrSymbol())
62 return nullptr;
63 return reinterpret_cast<StringOrSymbol *>(const_cast<Value *>(this));
64 }
66 if (!isSymbol())
67 return nullptr;
68 return reinterpret_cast<Symbol *>(const_cast<Value *>(this));
69 }
71 if (!isObject())
72 return nullptr;
73 return reinterpret_cast<Object*>(const_cast<Value *>(this));
74 }
76 if (!isManaged())
77 return nullptr;
78 return reinterpret_cast<Managed*>(const_cast<Value *>(this));
79 }
81 return isManagedOrUndefined() ? m() : nullptr;
82 }
83
85 {
86 Value v;
87 v.setM(m);
88 return v;
89 }
90
91 int toUInt16() const;
92 inline int toInt32() const;
93 inline unsigned int toUInt32() const;
94 qint64 toLength() const;
95 inline qint64 toIndex() const;
96
97 bool toBoolean() const {
98 if (integerCompatible())
99 return static_cast<bool>(int_32());
100
101 return toBooleanImpl(*this);
102 }
103 static bool toBooleanImpl(Value val);
104 double toInteger() const;
105 inline ReturnedValue convertedToNumber() const;
106 inline double toNumber() const;
107 static double toNumberImpl(Value v);
108 double toNumberImpl() const { return toNumberImpl(*this); }
109
110 QString toQStringNoThrow() const;
111 QString toQString() const;
112 QString toQString(bool *ok) const;
113
115 if (isString())
116 return reinterpret_cast<Heap::String *>(m());
117 return toString(e, *this);
118 }
119 QV4::PropertyKey toPropertyKey(ExecutionEngine *e) const;
120
122 Heap::Object *toObject(ExecutionEngine *e) const {
123 if (isObject())
124 return reinterpret_cast<Heap::Object *>(m());
125 return toObject(e, *this);
126 }
127 static Heap::Object *toObject(ExecutionEngine *e, Value val);
128
129 inline bool isPrimitive() const;
130
131 template <typename T>
132 const T *as() const {
133 if (!isManaged())
134 return nullptr;
135
136 Q_ASSERT(m()->internalClass->vtable);
137#if !defined(QT_NO_QOBJECT_CHECK)
138 static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
139#endif
140 const VTable *vt = m()->internalClass->vtable;
141 while (vt) {
142 if (vt == T::staticVTable())
143 return static_cast<const T *>(this);
144 vt = vt->parent;
145 }
146 return nullptr;
147 }
148 template <typename T>
149 T *as() {
150 if (isManaged())
151 return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
152 else
153 return nullptr;
154 }
155
156 template<typename T> inline T *cast() {
157 return static_cast<T *>(managed());
158 }
159 template<typename T> inline const T *cast() const {
160 return static_cast<const T *>(managed());
161 }
162
163 uint asArrayLength(bool *ok) const;
164
166 {
167 return fromStaticValue(StaticValue::fromReturnedValue(val));
168 }
169
170 // As per ES specs
171 bool sameValue(Value other) const;
172 bool sameValueZero(Value other) const;
173
174 inline void mark(MarkStack *markStack);
175
176 static double toInteger(double d) { return StaticValue::toInteger(d); }
177 static int toInt32(double d) { return StaticValue::toInt32(d); }
178 static unsigned int toUInt32(double d) { return StaticValue::toUInt32(d); }
179 inline static constexpr Value emptyValue()
180 {
181 return fromStaticValue(StaticValue::emptyValue());
182 }
183 static inline constexpr Value fromBoolean(bool b)
184 {
185 return fromStaticValue(StaticValue::fromBoolean(b));
186 }
187 static inline constexpr Value fromInt32(int i)
188 {
189 return fromStaticValue(StaticValue::fromInt32(i));
190 }
191 inline static constexpr Value undefinedValue()
192 {
193 return fromStaticValue(StaticValue::undefinedValue());
194 }
195 static inline constexpr Value nullValue()
196 {
197 return fromStaticValue(StaticValue::nullValue());
198 }
199 static inline Value fromDouble(double d)
200 {
201 return fromStaticValue(StaticValue::fromDouble(d));
202 }
203 static inline Value fromUInt32(uint i)
204 {
205 return fromStaticValue(StaticValue::fromUInt32(i));
206 }
207
208 Value &operator =(const ScopedValue &v);
210 {
211 StaticValue::operator=(v);
212 return *this;
213 }
215 if (!m) {
216 setM(nullptr);
217 } else {
218 _val = reinterpret_cast<Value *>(m)->_val;
219 }
220 return *this;
221 }
223 setM(o);
224 return *this;
225 }
226
227 template<typename T>
228 Value &operator=(const Scoped<T> &t);
229};
230Q_STATIC_ASSERT(std::is_trivial_v<Value>);
232
233template<>
234inline StaticValue &StaticValue::operator=<Value>(const Value &value)
235{
236 _val = value._val;
237 return *this;
238}
239
240template<typename Managed>
242{
243 *static_cast<Value *>(this) = m;
244 return *this;
245}
246
247template<>
248inline Value &StaticValue::asValue<Value>()
249{
250 return *static_cast<Value *>(this);
251}
252
253template<>
254inline const Value &StaticValue::asValue<Value>() const
255{
256 return *static_cast<const Value *>(this);
257}
258
259template<>
260inline Value *CallData::argValues<Value>()
261{
262 return static_cast<Value *>(static_cast<StaticValue *>(args));
263}
264
265template<>
266inline const Value *CallData::argValues<Value>() const
267{
268 return static_cast<const Value *>(static_cast<const StaticValue *>(args));
269}
270
271template<typename HeapBase>
272inline Encode::Encode(HeapBase *o)
273{
274 val = Value::fromHeapObject(o).asReturnedValue();
275}
276
277inline void Value::mark(MarkStack *markStack)
278{
280 if (o)
281 o->mark(markStack);
282}
283
284inline bool Value::isString() const
285{
287 return b && b->internalClass->vtable->isString;
288}
289
291{
293 return b && b->internalClass->vtable->isStringOrSymbol;
294}
295
296bool Value::isSymbol() const
297{
299 return b && b->internalClass->vtable->isStringOrSymbol && !b->internalClass->vtable->isString;
300}
301
302inline bool Value::isObject() const
303
304{
306 return b && b->internalClass->vtable->isObject;
307}
308
309inline bool Value::isFunctionObject() const
310{
312 if (!b)
313 return false;
314 const VTable *vtable = b->internalClass->vtable;
315 return vtable->call || vtable->callAsConstructor;
316}
317
318inline bool Value::isPrimitive() const
319{
320 return !isObject();
321}
322
323inline double Value::toNumber() const
324{
325 if (isInteger())
326 return int_32();
327 if (isDouble())
328 return doubleValue();
329 return toNumberImpl();
330}
331
333{
334 if (isInteger() || isDouble())
335 return asReturnedValue();
336 Value v;
338 return v.asReturnedValue();
339}
340
341inline
343{
344 return Value::fromHeapObject(const_cast<Value::HeapBasePtr>(this)).asReturnedValue();
345}
346
347// For source compat with older code in other modules
349
350template<typename T>
352
353inline int Value::toInt32() const
354{
355 if (Q_LIKELY(integerCompatible()))
356 return int_32();
357
358 if (Q_LIKELY(isDouble()))
359 return QJSNumberCoercion::toInteger(doubleValue());
360
361 return QJSNumberCoercion::toInteger(toNumberImpl());
362}
363
364inline unsigned int Value::toUInt32() const
365{
366 return static_cast<unsigned int>(toInt32());
367}
368
370{
371 if (Q_LIKELY(integerCompatible()))
372 return int_32() < 0 ? 0 : int_32();
373 double i = Value::toInteger(isDouble() ? doubleValue() : toNumberImpl());
374 if (i <= 0)
375 return 0;
376 if (i > (static_cast<qint64>(1) << 53) - 1)
377 return (static_cast<qint64>(1) << 53) - 1;
378 return static_cast<qint64>(i);
379}
380
381inline qint64 Value::toIndex() const
382{
383 qint64 idx;
384 if (Q_LIKELY(integerCompatible())) {
385 idx = int_32();
386 } else {
387 idx = static_cast<qint64>(Value::toInteger(isDouble() ? doubleValue() : toNumberImpl()));
388 }
389 if (idx > (static_cast<qint64>(1) << 53) - 1)
390 idx = -1;
391 return idx;
392}
393
394inline double Value::toInteger() const
395{
396 if (integerCompatible())
397 return int_32();
398
399 return Value::toInteger(isDouble() ? doubleValue() : toNumberImpl());
400}
401
402
403template <size_t o>
404struct HeapValue : Value {
405 static constexpr size_t offset = o;
407 HeapBasePtr base = reinterpret_cast<HeapBasePtr>(this) - (offset/sizeof(Heap::Base));
408 Q_ASSERT(base->inUse());
409 return base;
410 }
411
412 void set(EngineBase *e, const Value &newVal) {
413 WriteBarrier::write(e, base(), data_ptr(), newVal.asReturnedValue());
414 }
416 WriteBarrier::write(e, base(), data_ptr(), b->asReturnedValue());
417 }
418};
419
420template <size_t o>
422 static constexpr size_t offset = o;
426
428 Value::HeapBasePtr base = reinterpret_cast<Value::HeapBasePtr>(this)
429 - (offset/sizeof(Heap::Base));
430 Q_ASSERT(base->inUse());
431 return base;
432 }
433
435 WriteBarrier::write(e, base(), values[index].data_ptr(), v.asReturnedValue());
436 }
438 WriteBarrier::write(e, base(), values[index].data_ptr(), Value::fromHeapObject(b).asReturnedValue());
439 }
440 inline const Value &operator[] (uint index) const {
441 Q_ASSERT(index < alloc);
442 return values[index];
443 }
444 inline const Value *data() const {
445 return values;
446 }
447
448 void mark(MarkStack *markStack) {
449 for (Value *v = values, *end = values + alloc; v < end; ++v)
450 v->mark(markStack);
451 }
452};
453
454// It's really important that the offset of values in this structure is
455// constant across all architecture, otherwise JIT cross-compiled code will
456// have wrong offsets between host and target.
457Q_STATIC_ASSERT(offsetof(ValueArray<0>, values) == 8);
458
461public:
462
463 OptionalReturnedValue() : value(Value::emptyValue().asReturnedValue()) {}
465 : value(v)
466 {
467 Q_ASSERT(!Value::fromReturnedValue(v).isEmpty());
468 }
469
470 ReturnedValue operator->() const { return value; }
471 ReturnedValue operator*() const { return value; }
472 explicit operator bool() const { return !Value::fromReturnedValue(value).isEmpty(); }
473};
474
475}
476
478
479#endif // QV4VALUE_DEF_P_H
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
ReturnedValue operator*() const
Definition qv4value_p.h:471
OptionalReturnedValue(ReturnedValue v)
Definition qv4value_p.h:464
ReturnedValue operator->() const
Definition qv4value_p.h:470
QJSManagedValue managed(std::move(val), &engine)
Combined button and popup list for selecting options.
quint64 ReturnedValue
ReturnedValue value_convert(ExecutionEngine *e, const Value &v)
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:108
#define Q_LIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint index
[2]
GLuint GLuint end
GLenum GLuint GLintptr offset
GLuint GLfloat * val
GLdouble GLdouble t
Definition qopenglext.h:243
const void * data_ptr(const QTransform &t)
Definition qpainter_p.h:48
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QML_NEARLY_ALWAYS_INLINE
unsigned long long quint64
Definition qtypes.h:61
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
static const uint base
Definition qurlidna.cpp:20
static uint toIndex(ExecutionEngine *e, const Value &v)
static int toInt32(Value v)
QSharedPointer< T > other(t)
[5]
char * toString(const MyType &t)
[31]
StaticValue args[1]
constexpr Encode(bool b)
void set(EngineBase *e, HeapBasePtr b)
Definition qv4value_p.h:415
HeapBasePtr base()
Definition qv4value_p.h:406
void set(EngineBase *e, const Value &newVal)
Definition qv4value_p.h:412
ReturnedValue asReturnedValue() const
Definition qv4value_p.h:342
StaticValue & operator=(ReturnedValue v)
bool isInteger() const
constexpr ReturnedValue asReturnedValue() const
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const
QV4_NEARLY_ALWAYS_INLINE void setDouble(double d)
bool isDouble() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
const VTable *const parent
Definition qv4vtable_p.h:61
CallAsConstructor callAsConstructor
Definition qv4vtable_p.h:94
const Value * data() const
Definition qv4value_p.h:444
void set(EngineBase *e, uint index, Value v)
Definition qv4value_p.h:434
void set(EngineBase *e, uint index, Value::HeapBasePtr b)
Definition qv4value_p.h:437
void mark(MarkStack *markStack)
Definition qv4value_p.h:448
Value::HeapBasePtr base()
Definition qv4value_p.h:427
bool isStringOrSymbol() const
Definition qv4value_p.h:290
void mark(MarkStack *markStack)
Definition qv4value_p.h:277
qint64 toLength() const
Definition qv4value_p.h:369
qint64 toIndex() const
Definition qv4value_p.h:381
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
Value & operator=(ReturnedValue v)
Definition qv4value_p.h:209
bool isFunctionObject() const
Definition qv4value_p.h:309
Heap::String * toString(ExecutionEngine *e) const
Definition qv4value_p.h:114
bool isString() const
Definition qv4value_p.h:284
bool isPrimitive() const
Definition qv4value_p.h:318
constexpr Value(quint64 val)
Definition qv4value_p.h:42
static constexpr Value fromStaticValue(StaticValue staticValue)
Definition qv4value_p.h:44
int toInt32() const
Definition qv4value_p.h:353
static unsigned int toUInt32(double d)
Definition qv4value_p.h:178
Value & operator=(ManagedPtr m)
Definition qv4value_p.h:214
Value()=default
bool toBoolean() const
Definition qv4value_p.h:97
unsigned int toUInt32() const
Definition qv4value_p.h:364
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
Definition qv4value_p.h:55
QML_NEARLY_ALWAYS_INLINE ManagedPtr managed() const
Definition qv4value_p.h:75
static constexpr Value fromBoolean(bool b)
Definition qv4value_p.h:183
static constexpr Value undefinedValue()
Definition qv4value_p.h:191
static Value fromDouble(double d)
Definition qv4value_p.h:199
double toNumber() const
Definition qv4value_p.h:323
const T * cast() const
Definition qv4value_p.h:159
static double toInteger(double d)
Definition qv4value_p.h:176
QML_NEARLY_ALWAYS_INLINE Object * objectValue() const
Definition qv4value_p.h:70
QML_NEARLY_ALWAYS_INLINE StringOrSymbol * stringOrSymbolValue() const
Definition qv4value_p.h:60
static Value fromHeapObject(HeapBasePtr m)
Definition qv4value_p.h:84
static constexpr Value fromReturnedValue(ReturnedValue val)
Definition qv4value_p.h:165
Value & operator=(HeapBasePtr o)
Definition qv4value_p.h:222
const T * as() const
Definition qv4value_p.h:132
double toNumberImpl() const
Definition qv4value_p.h:108
ReturnedValue convertedToNumber() const
Definition qv4value_p.h:332
QML_NEARLY_ALWAYS_INLINE Symbol * symbolValue() const
Definition qv4value_p.h:65
QML_NEARLY_ALWAYS_INLINE Value::HeapBasePtr heapObject() const
Definition qv4value_p.h:80
static constexpr Value emptyValue()
Definition qv4value_p.h:179
bool isSymbol() const
Definition qv4value_p.h:296
static constexpr Value nullValue()
Definition qv4value_p.h:195
static int toInt32(double d)
Definition qv4value_p.h:177
double toInteger() const
Definition qv4value_p.h:394
Heap::Object * toObject(ExecutionEngine *e) const
Definition qv4value_p.h:122
static Value fromUInt32(uint i)
Definition qv4value_p.h:203
bool isObject() const
Definition qv4value_p.h:302