Cleanup some of the casting code
authorLars Knoll <lars.knoll@theqtcompany.com>
Fri, 13 Feb 2015 09:02:28 +0000 (10:02 +0100)
committerLars Knoll <lars.knoll@digia.com>
Fri, 20 Mar 2015 11:17:11 +0000 (11:17 +0000)
Get rid of value_cast, and move the Managed::as()
method into Value.

Change-Id: I440ac44ae77f4fda1a8a837383fe631f432f6532
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
17 files changed:
src/qml/jsruntime/qv4arraydata.cpp
src/qml/jsruntime/qv4arraydata_p.h
src/qml/jsruntime/qv4booleanobject.cpp
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4errorobject_p.h
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4global_p.h
src/qml/jsruntime/qv4internalclass_p.h
src/qml/jsruntime/qv4managed.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4serialize.cpp
src/qml/jsruntime/qv4value_inl_p.h
src/qml/jsruntime/qv4value_p.h
src/qml/memory/qv4heap_p.h

index b788598..a8527de 100644 (file)
@@ -39,7 +39,7 @@
 
 using namespace QV4;
 
-const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
+const QV4::VTable QV4::ArrayData::static_vtbl = {
     0,
     QV4::ArrayData::IsExecutionContext,
     QV4::ArrayData::IsString,
index 915e862..667827d 100644 (file)
@@ -47,7 +47,7 @@ namespace QV4 {
         Q_MANAGED_CHECK \
         typedef QV4::Heap::DataClass Data; \
         static const QV4::ArrayVTable static_vtbl; \
-        static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+        static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
         V4_MANAGED_SIZE_TEST \
         const Data *d() const { return static_cast<const Data *>(m); } \
         Data *d() { return static_cast<Data *>(m); }
@@ -57,7 +57,7 @@ struct ArrayData;
 
 struct ArrayVTable
 {
-    ManagedVTable managedVTable;
+    VTable vTable;
     uint type;
     Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
     ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
index 988af0c..474405e 100644 (file)
@@ -74,7 +74,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
     if (ctx->thisObject().isBoolean()) {
         result = ctx->thisObject().booleanValue();
     } else {
-        BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+        const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
         if (!thisObject)
             return ctx->engine()->throwTypeError();
         result = thisObject->value();
@@ -88,7 +88,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
     if (ctx->thisObject().isBoolean())
         return ctx->thisObject().asReturnedValue();
 
-    BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
+    const BooleanObject *thisObject = ctx->thisObject().as<BooleanObject>();
     if (!thisObject)
         return ctx->engine()->throwTypeError();
 
index 0ace88b..fd3b662 100644 (file)
@@ -1184,7 +1184,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
     Q_ASSERT (!value.isEmpty());
     QV4::Scope scope(e);
 
-    if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
+    if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
         return v->d()->data;
 
     if (typeHint == QVariant::Bool)
@@ -1253,7 +1253,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
         return value.asDouble();
     if (value.isString())
         return value.stringValue()->toQString();
-    if (QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
+    if (const QV4::QQmlLocaleData *ld = value.as<QV4::QQmlLocaleData>())
         return ld->d()->locale;
     if (QV4::DateObject *d = value.asDateObject())
         return d->toQDateTime();
@@ -1681,12 +1681,12 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
             return true;
         } break;
     case QMetaType::QRegExp:
-        if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
+        if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
             *reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
             return true;
         } break;
     case QMetaType::QObjectStar: {
-        QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
+        const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
         if (qobjectWrapper || value.isNull()) {
             *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
             return true;
@@ -1766,7 +1766,7 @@ bool ExecutionEngine::metaTypeFromJS(const QV4::Value &value, int type, void *da
     }
 #endif
 
-    // Try to use magic; for compatibility with qscriptvalue_cast.
+    // Try to use magic; for compatibility with qjsvalue_cast.
 
     QByteArray name = QMetaType::typeName(type);
     if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
index 071f5b8..f8278a2 100644 (file)
@@ -141,8 +141,8 @@ struct ErrorObject: Object {
 };
 
 template<>
-inline ErrorObject *value_cast(const Value &v) {
-    return v.asErrorObject();
+inline const ErrorObject *Value::as() const {
+    return asErrorObject();
 }
 
 struct EvalErrorObject: ErrorObject {
index ce00dfb..a429e74 100644 (file)
@@ -144,8 +144,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
 };
 
 template<>
-inline FunctionObject *value_cast(const Value &v) {
-    return v.asFunctionObject();
+inline const FunctionObject *Value::as() const {
+    return asFunctionObject();
 }
 
 struct FunctionCtor: FunctionObject
index 4b08194..3385547 100644 (file)
@@ -168,7 +168,7 @@ struct Property;
 struct Value;
 struct Lookup;
 struct ArrayData;
-struct ManagedVTable;
+struct VTable;
 
 struct BooleanObject;
 struct NumberObject;
index 3289058..80590fe 100644 (file)
@@ -46,7 +46,7 @@ struct String;
 struct ExecutionEngine;
 struct Object;
 struct Identifier;
-struct ManagedVTable;
+struct VTable;
 
 struct PropertyHashData;
 struct PropertyHash
index a6bce08..5461900 100644 (file)
@@ -38,7 +38,7 @@
 using namespace QV4;
 
 
-const ManagedVTable Managed::static_vtbl =
+const VTable Managed::static_vtbl =
 {
     0,
     Managed::IsExecutionContext,
index 5a4f305..79b6de4 100644 (file)
@@ -65,8 +65,8 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
         Q_MANAGED_CHECK \
         typedef QV4::Heap::DataClass Data; \
         typedef superClass SuperClass; \
-        static const QV4::ManagedVTable static_vtbl; \
-        static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
+        static const QV4::VTable static_vtbl; \
+        static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
         V4_MANAGED_SIZE_TEST \
         QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
 
@@ -86,23 +86,6 @@ struct GCDeletable
     bool lastCall;
 };
 
-struct ManagedVTable
-{
-    const ManagedVTable * const parent;
-    uint isExecutionContext : 1;
-    uint isString : 1;
-    uint isObject : 1;
-    uint isFunctionObject : 1;
-    uint isErrorObject : 1;
-    uint isArrayData : 1;
-    uint unused : 18;
-    uint type : 8;
-    const char *className;
-    void (*destroy)(Heap::Base *);
-    void (*markObjects)(Heap::Base *, ExecutionEngine *e);
-    bool (*isEqualTo)(Managed *m, Managed *other);
-};
-
 #define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
 {     \
     parentVTable, \
@@ -121,7 +104,7 @@ struct ManagedVTable
 }
 
 #define DEFINE_MANAGED_VTABLE(classname) \
-const QV4::ManagedVTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
+const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
 
 struct Q_QML_PRIVATE_EXPORT Managed : Value
 {
@@ -167,35 +150,6 @@ public:
     };
     Q_MANAGED_TYPE(Invalid)
 
-    template <typename T>
-    T *as() {
-        Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
-        static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(this));
-#endif
-        const ManagedVTable *vt = d()->vtable;
-        while (vt) {
-            if (vt == T::staticVTable())
-                return static_cast<T *>(this);
-            vt = vt->parent;
-        }
-        return 0;
-    }
-    template <typename T>
-    const T *as() const {
-        Q_ASSERT(d()->vtable);
-#if !defined(QT_NO_QOBJECT_CHECK)
-        static_cast<T *>(this)->qt_check_for_QMANAGED_macro(static_cast<T *>(const_cast<Managed *>(this)));
-#endif
-        const ManagedVTable *vt = d()->vtable;
-        while (vt) {
-            if (vt == T::staticVTable())
-                return static_cast<T *>(this);
-            vt = vt->parent;
-        }
-        return 0;
-    }
-
     String *asString() { return d()->vtable->isString ? reinterpret_cast<String *>(this) : 0; }
     Object *asObject() { return d()->vtable->isObject ? reinterpret_cast<Object *>(this) : 0; }
     ArrayObject *asArrayObject() { return d()->vtable->type == Type_ArrayObject ? reinterpret_cast<ArrayObject *>(this) : 0; }
@@ -231,8 +185,8 @@ private:
 
 
 template<>
-inline Managed *value_cast(const Value &v) {
-    return v.asManaged();
+inline const Managed *Value::as() const {
+    return asManaged();
 }
 
 template<typename T>
index 3177a73..7758630 100644 (file)
@@ -70,7 +70,7 @@ struct Object : Base {
         Q_MANAGED_CHECK \
         typedef superClass SuperClass; \
         static const QV4::ObjectVTable static_vtbl; \
-        static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+        static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
         V4_MANAGED_SIZE_TEST \
         Data *d() const { return static_cast<Data *>(m); }
 
@@ -80,13 +80,13 @@ struct Object : Base {
         typedef QV4::Heap::DataClass Data; \
         typedef superClass SuperClass; \
         static const QV4::ObjectVTable static_vtbl; \
-        static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+        static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
         V4_MANAGED_SIZE_TEST \
         QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
 
 struct ObjectVTable
 {
-    ManagedVTable managedVTable;
+    VTable vTable;
     ReturnedValue (*call)(Managed *, CallData *data);
     ReturnedValue (*construct)(Managed *, CallData *data);
     ReturnedValue (*get)(Managed *, String *name, bool *hasProperty);
@@ -106,7 +106,7 @@ struct ObjectVTable
 #define DEFINE_OBJECT_VTABLE(classname) \
 const QV4::ObjectVTable classname::static_vtbl =    \
 {     \
-    DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.managedVTable), \
+    DEFINE_MANAGED_VTABLE_INT(classname, &classname::SuperClass::static_vtbl == &Object::static_vtbl ? 0 : &classname::SuperClass::static_vtbl.vTable), \
     call,                                       \
     construct,                                  \
     get,                                        \
@@ -458,13 +458,13 @@ inline void Object::arraySet(uint index, const Value &value)
 }
 
 template<>
-inline Object *value_cast(const Value &v) {
-    return v.asObject();
+inline const Object *Value::as() const {
+    return asObject();
 }
 
 template<>
-inline ArrayObject *value_cast(const Value &v) {
-    return v.asArrayObject();
+inline const ArrayObject *Value::as() const {
+    return asArrayObject();
 }
 
 #ifndef V4_BOOTSTRAP
index 7a5890f..5bb7bac 100644 (file)
@@ -1598,9 +1598,9 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
         type = callType;
     } else if (callType == QMetaType::QObjectStar) {
         qobjectPtr = 0;
-        if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+        if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
             qobjectPtr = qobjectWrapper->object();
-        else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
+        else if (const QV4::QmlTypeWrapper *qmlTypeWrapper = value.as<QV4::QmlTypeWrapper>())
             queryEngine = qmlTypeWrapper->isSingleton();
         type = callType;
     } else if (callType == qMetaTypeId<QVariant>()) {
@@ -1622,7 +1622,7 @@ void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
             }
         } else {
             QObject *o = 0;
-            if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
+            if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
                 o = qobjectWrapper->object();
             qlistPtr->append(o);
         }
index 908248f..b469567 100644 (file)
@@ -202,7 +202,7 @@ struct Scoped
 {
     enum _Convert { Convert };
 
-    inline void setPointer(Managed *p) {
+    inline void setPointer(const Managed *p) {
         ptr->m = p ? p->m : 0;
 #if QT_POINTER_SIZE == 4
         ptr->tag = QV4::Value::Managed_Type;
@@ -225,7 +225,7 @@ struct Scoped
     Scoped(const Scope &scope, const Value &v)
     {
         ptr = scope.engine->jsStackTop++;
-        setPointer(value_cast<T>(v));
+        setPointer(v.as<T>());
 #ifndef QT_NO_DEBUG
         ++scope.size;
 #endif
@@ -235,7 +235,7 @@ struct Scoped
         Value v;
         v = o;
         ptr = scope.engine->jsStackTop++;
-        setPointer(value_cast<T>(v));
+        setPointer(v.as<T>());
 #ifndef QT_NO_DEBUG
         ++scope.size;
 #endif
@@ -243,7 +243,7 @@ struct Scoped
     Scoped(const Scope &scope, const ScopedValue &v)
     {
         ptr = scope.engine->jsStackTop++;
-        setPointer(value_cast<T>(*v.ptr));
+        setPointer(v.ptr->as<T>());
 #ifndef QT_NO_DEBUG
         ++scope.size;
 #endif
@@ -261,7 +261,7 @@ struct Scoped
     Scoped(const Scope &scope, const Value *v)
     {
         ptr = scope.engine->jsStackTop++;
-        setPointer(v ? value_cast<T>(*v) : 0);
+        setPointer(v ? v->as<T>() : 0);
 #ifndef QT_NO_DEBUG
         ++scope.size;
 #endif
@@ -287,7 +287,7 @@ struct Scoped
     Scoped(const Scope &scope, const ReturnedValue &v)
     {
         ptr = scope.engine->jsStackTop++;
-        setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+        setPointer(QV4::Value::fromReturnedValue(v).as<T>());
 #ifndef QT_NO_DEBUG
         ++scope.size;
 #endif
@@ -302,9 +302,7 @@ struct Scoped
     }
 
     Scoped<T> &operator=(Heap::Base *o) {
-        Value v;
-        v = o;
-        setPointer(value_cast<T>(v));
+        setPointer(Value::fromHeapObject(o).as<T>());
         return *this;
     }
     Scoped<T> &operator=(typename T::Data *t) {
@@ -312,16 +310,16 @@ struct Scoped
         return *this;
     }
     Scoped<T> &operator=(const Value &v) {
-        setPointer(value_cast<T>(v));
+        setPointer(v.as<T>());
         return *this;
     }
     Scoped<T> &operator=(Value *v) {
-        setPointer(v ? value_cast<T>(*v) : 0);
+        setPointer(v ? v->as<T>() : 0);
         return *this;
     }
 
     Scoped<T> &operator=(const ReturnedValue &v) {
-        setPointer(value_cast<T>(QV4::Value::fromReturnedValue(v)));
+        setPointer(QV4::Value::fromReturnedValue(v).as<T>());
         return *this;
     }
 
index e669924..43fe9dd 100644 (file)
@@ -199,7 +199,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
         reserve(data, sizeof(quint32) + sizeof(double));
         push(data, valueheader(WorkerDate));
         push(data, d->date().asDouble());
-    } else if (RegExpObject *re = v.as<RegExpObject>()) {
+    } else if (const RegExpObject *re = v.as<RegExpObject>()) {
         quint32 flags = re->flags();
         QString pattern = re->source();
         int length = pattern.length() + 1;
@@ -218,7 +218,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, ExecutionEngine
         char *buffer = data.data() + offset;
 
         memcpy(buffer, pattern.constData(), length*sizeof(QChar));
-    } else if (QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
+    } else if (const QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
         // XXX TODO: Generalize passing objects between the main thread and worker scripts so
         // that others can trivially plug in their elements.
         QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
index bf1fbdd..1cb93f9 100644 (file)
@@ -273,12 +273,9 @@ inline ErrorObject *Value::asErrorObject() const
     return isObject() ? managed()->asErrorObject() : 0;
 }
 
-template<typename T>
-inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
-
 template<>
-inline String *value_cast(const Value &v) {
-    return v.asString();
+inline const String *Value::as() const {
+    return asString();
 }
 
 template<>
index 71ffae4..20d7404 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <QtCore/QString>
 #include "qv4global_p.h"
+#include <private/qv4heap_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -313,7 +314,28 @@ struct Q_QML_PRIVATE_EXPORT Value
     inline ArrayObject *asArrayObject() const;
     inline ErrorObject *asErrorObject() const;
 
-    template<typename T> inline T *as() const;
+    template <typename T>
+    const T *as() const {
+        if (!m || !isManaged())
+            return 0;
+
+        Q_ASSERT(m->vtable);
+#if !defined(QT_NO_QOBJECT_CHECK)
+        static_cast<const T *>(this)->qt_check_for_QMANAGED_macro(static_cast<const T *>(this));
+#endif
+        const VTable *vt = m->vtable;
+        while (vt) {
+            if (vt == T::staticVTable())
+                return static_cast<const T *>(this);
+            vt = vt->parent;
+        }
+        return 0;
+    }
+    template <typename T>
+    T *as() {
+        return const_cast<T *>(const_cast<const Value *>(this)->as<T>());
+    }
+
     template<typename T> inline T *cast() {
         return static_cast<T *>(managed());
     }
@@ -479,12 +501,6 @@ private:
 };
 
 template<typename T>
-T *value_cast(const Value &v)
-{
-    return v.as<T>();
-}
-
-template<typename T>
 ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
 
 }
index 3a78854..c396f0f 100644 (file)
@@ -40,11 +40,28 @@ QT_BEGIN_NAMESPACE
 
 namespace QV4 {
 
+struct VTable
+{
+    const VTable * const parent;
+    uint isExecutionContext : 1;
+    uint isString : 1;
+    uint isObject : 1;
+    uint isFunctionObject : 1;
+    uint isErrorObject : 1;
+    uint isArrayData : 1;
+    uint unused : 18;
+    uint type : 8;
+    const char *className;
+    void (*destroy)(Heap::Base *);
+    void (*markObjects)(Heap::Base *, ExecutionEngine *e);
+    bool (*isEqualTo)(Managed *m, Managed *other);
+};
+
 namespace Heap {
 
 struct Q_QML_EXPORT Base {
     union {
-        const ManagedVTable *vtable;
+        const VTable *vtable;
         quintptr mm_data;
     };
 
@@ -57,8 +74,8 @@ struct Q_QML_EXPORT Base {
         PointerMask = ~0x3
     };
 
-    ManagedVTable *gcGetVtable() const {
-        return reinterpret_cast<ManagedVTable *>(mm_data & PointerMask);
+    VTable *gcGetVtable() const {
+        return reinterpret_cast<VTable *>(mm_data & PointerMask);
     }
     inline bool isMarked() const {
         return mm_data & MarkBit;