aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi/qjsvalue_p.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@theqtcompany.com>2015-01-14 16:22:33 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2015-01-21 18:22:52 +0100
commit8209f35b7961b7ea6867d7ebfb5288dcf40ecd71 (patch)
treef9e8b5083788574b75d7dba7f4ca1c60eded86fe /src/qml/jsapi/qjsvalue_p.h
parentd8131513b07d3f0a6d749c9961b294fc955fed6d (diff)
Rework QJSValue internals
Use a flagged pointer to either store a pointer to a QV4::Value (from the persistent storage) or a pointer to a QVariant in QJSValue::d. Like this we don't need to malloc to create a QJSValue for most use cases. Significantly reduces the memory consumption of QJSValue and speeds it up a lot. Change-Id: I10902cc4b6cc3f43d3f816875dc6c4bbb6b4490f Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsapi/qjsvalue_p.h')
-rw-r--r--src/qml/jsapi/qjsvalue_p.h133
1 files changed, 93 insertions, 40 deletions
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 3d7afdbd75..83dbe82f76 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -57,64 +57,117 @@
QT_BEGIN_NAMESPACE
-/*!
- \internal
- \class QJSValuePrivate
-*/
-class Q_QML_PRIVATE_EXPORT QJSValuePrivate
+class QJSValuePrivate
{
public:
- QJSValuePrivate()
- : refcount(1)
- {}
- QJSValuePrivate(QV4::ExecutionEngine *e, const QV4::ValueRef v)
- : refcount(1),
- persistent(e, v)
+ static inline QV4::Value *getValue(const QJSValue *jsval)
{
- Q_ASSERT(!v->isEmpty());
+ if (jsval->d & 3)
+ return 0;
+ return reinterpret_cast<QV4::Value *>(jsval->d);
}
- QJSValuePrivate(QV4::ExecutionEngine *e, QV4::ReturnedValue v)
- : refcount(1),
- persistent(e, v)
+
+ static inline QVariant *getVariant(const QJSValue *jsval)
{
+ if (jsval->d & 1)
+ return reinterpret_cast<QVariant *>(jsval->d & ~3);
+ return 0;
}
- explicit QJSValuePrivate(const QVariant &v)
- : refcount(1),
- unboundData(v)
- {
+
+ static inline void setVariant(QJSValue *jsval, const QVariant &v) {
+ QVariant *val = new QVariant(v);
+ jsval->d = reinterpret_cast<quintptr>(val) | 1;
}
- bool checkEngine(QV4::ExecutionEngine *e) {
- if (persistent.isEmpty())
- getValue(e);
- return persistent.engine() == e;
+ static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, QV4::ValueRef v) {
+ QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
+ *value = v;
+ jsval->d = reinterpret_cast<quintptr>(value);
}
- QV4::ReturnedValue getValue(QV4::ExecutionEngine *e);
+ static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, QV4::ReturnedValue v) {
+ QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
+ *value = v;
+ jsval->d = reinterpret_cast<quintptr>(value);
+ }
- static QJSValuePrivate *get(const QJSValue &v) { return v.d; }
- QV4::ExecutionEngine *engine() const { return persistent.engine(); }
+ static QV4::ReturnedValue convertedToValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
+ {
+ QV4::Value *v = getValue(&jsval);
+ if (!v) {
+ QVariant *variant = getVariant(&jsval);
+ v = e->memoryManager->m_persistentValues->allocate();
+ *v = variant ? e->fromVariant(*variant) : QV4::Encode::undefined();
+ jsval.d = reinterpret_cast<quintptr>(v);
+ delete variant;
+ }
+
+ if (QV4::PersistentValueStorage::getEngine(v) != e) {
+ qWarning("JSValue can't be reassigned to another engine.");
+ return QV4::Encode::undefined();
+ }
- void ref() { ++refcount; }
- void deref() {
- if (!--refcount)
- delete this;
+ return v->asReturnedValue();
}
- QV4::Value *valueForData(QV4::Value *scratch) const {
- QV4::Value *v = persistent.valueRef();
+ static QV4::Value *valueForData(const QJSValue *jsval, QV4::Value *scratch)
+ {
+ QV4::Value *v = getValue(jsval);
if (v)
return v;
- *scratch = primitiveValueForUnboundData();
- return (scratch->isEmpty() ? 0 : scratch);
+ v = scratch;
+ QVariant *variant = getVariant(jsval);
+ if (!variant) {
+ *v = QV4::Encode::undefined();
+ return v;
+ }
+
+ switch (variant->userType()) {
+ case QMetaType::UnknownType:
+ case QMetaType::Void:
+ *v = QV4::Encode::undefined();
+ break;
+ case QMetaType::VoidStar:
+ *v = QV4::Encode::null();
+ break;
+ case QMetaType::Bool:
+ *v = QV4::Encode(variant->toBool());
+ break;
+ case QMetaType::Double:
+ *v = QV4::Encode(variant->toDouble());
+ break;
+ case QMetaType::Int:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *v = QV4::Encode(variant->toInt());
+ break;
+ case QMetaType::UInt:
+ *v = QV4::Encode(variant->toUInt());
+ break;
+ default:
+ return 0;
+ }
+ return v;
+ }
+
+ static QV4::ExecutionEngine *engine(const QJSValue *jsval) {
+ QV4::Value *v = getValue(jsval);
+ return v ? QV4::PersistentValueStorage::getEngine(v) : 0;
}
- QV4::Value primitiveValueForUnboundData() const;
- int refcount;
- QV4::PersistentValue persistent;
- QVariant unboundData;
-private:
- QJSValuePrivate(QV4::ReturnedValue v) Q_DECL_EQ_DELETE;
+ static inline bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval) {
+ QV4::ExecutionEngine *v4 = engine(&jsval);
+ return !v4 || v4 == e;
+ }
+
+ static inline void free(QJSValue *jsval) {
+ if (QV4::Value *v = QJSValuePrivate::getValue(jsval))
+ QV4::PersistentValueStorage::free(v);
+ else if (QVariant *v = QJSValuePrivate::getVariant(jsval))
+ delete v;
+ }
};
QT_END_NAMESPACE