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>
26#include <QtCore/qthread.h>
32 static constexpr quint64 s_tagBits = 3;
33 static constexpr quint64 s_tagMask = (1 << s_tagBits) - 1;
35 static constexpr quint64 s_pointerBit = 0x1;
49 static_assert(quint64(
Kind::Null) <= s_tagMask);
56 static Kind tag(quint64 raw) {
return Kind(raw & s_tagMask); }
58#if QT_POINTER_SIZE == 4
62 return reinterpret_cast<
void *>(
raw >> 32);
72 static_assert(
alignof(
double) >= s_minAlignment);
78 Q_ASSERT(quint64(tag(raw)) & s_pointerBit);
79 return reinterpret_cast<
void *>(raw & ~s_tagMask);
84 Q_ASSERT(quint64(tag) & s_pointerBit);
85 return quintptr(pointer) | quint64(tag);
112 return (uintValue < uint(std::numeric_limits<
int>::max()))
113 ? encode(
int(uintValue))
114 : encode(
double(uintValue));
131 return static_cast<
double *>(pointer(v));
142 return static_cast<QV4::Value *>(pointer(v));
147 switch (qv4Value.type()) {
148 case QV4::StaticValue::Boolean_Type:
149 return encode(qv4Value.booleanValue());
150 case QV4::StaticValue::Integer_Type:
151 return encode(qv4Value.integerValue());
152 case QV4::StaticValue::Managed_Type: {
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();
160 QV4::WriteBarrier::markCustom(engine, [&](QV4::MarkStack *stack){
161 if constexpr (QV4::WriteBarrier::isInsertionBarrier)
162 managed->heapObject()->mark(stack);
167 case QV4::StaticValue::Double_Type:
168 return encode(qv4Value.doubleValue());
169 case QV4::StaticValue::Null_Type:
171 case QV4::StaticValue::Empty_Type:
174 case QV4::StaticValue::Undefined_Type:
178 return encodeUndefined();
184 return static_cast<QString *>(pointer(v));
189 return encodePointer(
new QString(std::move(stringValue)), Kind::QStringPtr);
194 return encodePointer(
new QString(std::move(stringValue)), Kind::QStringPtr);
200 setValue(&result, QV4::Value::fromReturnedValue(d));
208 if (
const QV4::Value *value = qv4ValuePtr(jsval->d))
209 return value->as<T>();
218 if (QV4::Value *value = qv4ValuePtr(jsval->d)) {
219 jsval->d = encodeUndefined();
228 switch (tag(jsval->d)) {
229 case Kind::BoolValue:
230 return QV4::Encode(boolValue(jsval->d));
232 return QV4::Encode(intValue(jsval->d));
233 case Kind::DoublePtr:
234 return QV4::Encode(*doublePtr(jsval->d));
236 return QV4::Encode::null();
243 return QV4::Encode::undefined();
251 if (
const QString *string = qStringPtr(jsval->d))
259 switch (tag(jsval->d)) {
260 case Kind::BoolValue:
261 return QV4::Encode(boolValue(jsval->d));
263 return QV4::Encode(intValue(jsval->d));
264 case Kind::DoublePtr:
265 return QV4::Encode(*doublePtr(jsval->d));
267 return QV4::Encode::null();
269 return qv4ValuePtr(jsval->d)->asReturnedValue();
275 return QV4::Encode::undefined();
280 jsval->d = encode(std::move(s));
290 static void setValue(QJSValue *jsval,
const QV4::Value &v)
292 jsval->d = encode(v);
299 jsval->d = encode(QV4::Value::fromHeapObject(e->newString(*string)));
307 const QJSValue &jsval)
310 return e->newString(*string)->asReturnedValue();
311 if (
const QV4::Value *val = asManagedType<QV4::Managed>(&jsval)) {
312 if (QV4::PersistentValueStorage::getEngine(val) == e)
313 return val->asReturnedValue();
315 qWarning(
"JSValue can't be reassigned to another engine.");
316 return QV4::Encode::undefined();
318 return asPrimitiveType(&jsval);
321 static QV4::ExecutionEngine *
engine(
const QJSValue *jsval)
324 if (
const QV4::Value *value = qv4ValuePtr(jsval->d))
325 return QV4::PersistentValueStorage::getEngine(value);
334 return !v4 || v4 == e;
337 static void free(QJSValue *jsval)
339 switch (tag(jsval->d)) {
346 delete doublePtr(jsval->d);
349 delete qStringPtr(jsval->d);
356 QV4::Value *m = qv4ValuePtr(jsval->d);
358 if (
QV4::ExecutionEngine *e = QV4::PersistentValueStorage::getEngine(m)) {
359 if (
QJSEngine *jsEngine = e->jsEngine()) {
360 if (jsEngine->thread() != QThread::currentThread()) {
361 QMetaObject::invokeMethod(
362 jsEngine, [m](){ QV4::PersistentValueStorage::free(m); });
367 QV4::PersistentValueStorage::free(m);
The QJSValueIterator class provides a Java-style iterator for QJSValue.
static quint64 encode(bool boolValue)
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
static void setString(QJSValue *jsval, QString s)
static bool boolValue(quint64 v)
static QV4::Value * qv4ValuePtr(quint64 v)
static int intValue(quint64 v)
static double * doublePtr(quint64 v)
static bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval)
static QV4::ExecutionEngine * engine(const QJSValue *jsval)
static quint64 encodePointer(void *pointer, Kind tag)
static QV4::Value * takeManagedValue(QJSValue *jsval)
static QV4::ReturnedValue asReturnedValue(const QJSValue *jsval)
static const QString * asQString(const QJSValue *jsval)
static quint64 encodeNull()
static constexpr quint64 s_minAlignment
static QString * qStringPtr(quint64 v)
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
static quint64 encode(const QV4::Value &qv4Value)
static void adoptPersistentValue(QJSValue *jsval, QV4::Value *v)
static QV4::ReturnedValue asPrimitiveType(const QJSValue *jsval)
static void setValue(QJSValue *jsval, const QV4::Value &v)
static void manageStringOnV4Heap(QV4::ExecutionEngine *e, QJSValue *jsval)
static quint64 encode(int intValue)
static const T * asManagedType(const QJSValue *jsval)
static quint64 encode(double doubleValue)
static void * pointer(quint64 raw)
static quint64 encode(QString stringValue)
static quint64 encodeUndefined()
static void free(QJSValue *jsval)
static Kind tag(quint64 raw)