From 39d7e330e64c2132828a040497a5b7326202b5b9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 27 Jan 2014 14:58:52 +0100 Subject: Make the Ref classes not template based Move to a class hierarchy that mirrors the main classes. This will allow moving functionality over into the Ref classes, as the current Managed classes become mainly something that holds the data. This is required to make objects movable by the GC. Change-Id: I4ca88ab0e5d8c88c8dc56d51937990500a33e0d9 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4debugging.cpp | 2 +- src/qml/jsruntime/qv4engine.cpp | 2 +- src/qml/jsruntime/qv4engine_p.h | 2 +- src/qml/jsruntime/qv4functionobject_p.h | 2 + src/qml/jsruntime/qv4global_p.h | 11 +-- src/qml/jsruntime/qv4managed_p.h | 136 +++++++++++++++----------------- src/qml/jsruntime/qv4object_p.h | 17 ++++ src/qml/jsruntime/qv4objectiterator.cpp | 16 ++-- src/qml/jsruntime/qv4objectiterator_p.h | 4 +- src/qml/jsruntime/qv4persistent_p.h | 7 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 3 +- src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 + src/qml/jsruntime/qv4regexpobject.cpp | 2 +- src/qml/jsruntime/qv4regexpobject_p.h | 3 +- src/qml/jsruntime/qv4scopedvalue_p.h | 44 ++++++----- src/qml/jsruntime/qv4script.cpp | 4 +- src/qml/jsruntime/qv4string_p.h | 2 + src/qml/jsruntime/qv4value_p.h | 2 +- src/qml/jsruntime/qv4variantobject_p.h | 2 + src/qml/qml/qqmlvmemetaobject.cpp | 3 +- 20 files changed, 142 insertions(+), 124 deletions(-) (limited to 'src/qml') diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp index 32d8c1fc4a..9ab1622fee 100644 --- a/src/qml/jsruntime/qv4debugging.cpp +++ b/src/qml/jsruntime/qv4debugging.cpp @@ -179,7 +179,7 @@ void Debugger::resume(Speed speed) return; if (!m_returnedValue.isUndefined()) - m_returnedValue = Primitive::undefinedValue(); + m_returnedValue = Encode::undefined(); clearTemporaryBreakPoints(); if (speed == StepOver) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 6de40f437c..16bacbfafd 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -560,7 +560,7 @@ Returned *ExecutionEngine::newRegExpObject(const QString &pattern, return newRegExpObject(re, global); } -Returned *ExecutionEngine::newRegExpObject(ManagedRef re, bool global) +Returned *ExecutionEngine::newRegExpObject(RegExpRef re, bool global) { RegExpObject *object = new (memoryManager) RegExpObject(this, re, global); return object->asReturned(); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 4fbef14f86..63c57b8478 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -317,7 +317,7 @@ public: Returned *newDateObject(const QDateTime &dt); Returned *newRegExpObject(const QString &pattern, int flags); - Returned *newRegExpObject(ManagedRef re, bool global); + Returned *newRegExpObject(RegExpRef re, bool global); Returned *newRegExpObject(const QRegExp &re); Returned *newErrorObject(const ValueRef value); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index d1fc56adad..af4ec024d5 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -155,6 +155,8 @@ inline FunctionObject *value_cast(const Value &v) { return v.asFunctionObject(); } +DEFINE_REF(FunctionObject, Object); + struct FunctionCtor: FunctionObject { V4_OBJECT diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index d3764d0515..746513cc2f 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -156,11 +156,12 @@ template struct Returned; typedef Returned ReturnedString; typedef Returned ReturnedObject; typedef Returned ReturnedFunctionObject; -template struct ManagedRef; -typedef ManagedRef StringRef; -typedef ManagedRef ObjectRef; -typedef ManagedRef ArrayObjectRef; -typedef ManagedRef FunctionObjectRef; +struct ManagedRef; +struct StringRef; +struct ObjectRef; +struct ArrayObjectRef; +struct FunctionObjectRef; +struct RegExpRef; struct PersistentValuePrivate; class PersistentValue; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index ed4637e4f5..8c6f2daf9b 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -353,80 +353,6 @@ private: friend struct ObjectIterator; }; -template -struct ManagedRef { - // Important: Do NOT add a copy constructor to this class or any derived class - // adding a copy constructor actually changes the calling convention, ie. - // is not even binary compatible. Adding it would break assumptions made - // in the jit'ed code. - ManagedRef(const ScopedValue); - ManagedRef(const Scoped &v); - ManagedRef(TypedValue &v) { ptr = &v; } - ManagedRef(Value &v) { - ptr = value_cast(v) ? &v : 0; - } - static ManagedRef fromValuePointer(Value *s) { - ManagedRef r(s); - if (sizeof(void *) == 8) - r.ptr->val = 0; - else - *r.ptr = Value::fromManaged(0); - return r; - } - - ManagedRef &operator=(T *t) - { - if (sizeof(void *) == 4) - ptr->tag = Value::Managed_Type; - ptr->m = t; - return *this; - } - ManagedRef &operator=(Returned *t) { - if (sizeof(void *) == 4) - ptr->tag = Value::Managed_Type; - ptr->m = t->getPointer(); - return *this; - } - - operator const T *() const { - return ptr ? static_cast(ptr->managed()) : 0; - } - const T *operator->() const { - return static_cast(ptr->managed()); - } - - operator T *() { - return ptr ? static_cast(ptr->managed()) : 0; - } - T *operator->() { - return static_cast(ptr->managed()); - } - - T *getPointer() const { - return static_cast(ptr->managed()); - } - ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); } - operator Returned *() const { return ptr ? Returned::create(getPointer()) : 0; } - - bool operator==(const ManagedRef &other) { - if (ptr == other.ptr) - return true; - return ptr && other.ptr && ptr->m == other.ptr->m; - } - bool operator!=(const ManagedRef &other) { - return !operator==(other); - } - bool operator!() const { return !ptr || !ptr->managed(); } - - static ManagedRef null() { return ManagedRef((Value *)0); } - bool isNull() const { return !ptr; } -protected: - ManagedRef(Value *v) { - ptr = v; - } - Value *ptr; -}; - template<> inline Managed *value_cast(const Value &v) { @@ -456,6 +382,68 @@ inline FunctionObject *managed_cast(Managed *m) } +Value *extractValuePointer(const ScopedValue &); +template +Value *extractValuePointer(const Scoped &); + +#define DEFINE_REF_METHODS(Class, Base) \ + Class##Ref(const QV4::ScopedValue &v) \ + { QV4::Value *val = extractValuePointer(v); ptr = QV4::value_cast(*val) ? val : 0; } \ + Class##Ref(const QV4::Scoped &v) { ptr = extractValuePointer(v); } \ + Class##Ref(QV4::TypedValue &v) { ptr = &v; } \ + Class##Ref(QV4::Value &v) { ptr = QV4::value_cast(v) ? &v : 0; } \ + Class##Ref &operator=(Class *t) { \ + if (sizeof(void *) == 4) \ + ptr->tag = QV4::Value::Managed_Type; \ + ptr->m = t; \ + return *this; \ + } \ + Class##Ref &operator=(QV4::Returned *t) { \ + if (sizeof(void *) == 4) \ + ptr->tag = QV4::Value::Managed_Type; \ + ptr->m = t->getPointer(); \ + return *this; \ + } \ + operator const Class *() const { return ptr ? static_cast(ptr->managed()) : 0; } \ + const Class *operator->() const { return static_cast(ptr->managed()); } \ + operator Class *() { return ptr ? static_cast(ptr->managed()) : 0; } \ + Class *operator->() { return static_cast(ptr->managed()); } \ + Class *getPointer() const { return static_cast(ptr->managed()); } \ + operator QV4::Returned *() const { return ptr ? QV4::Returned::create(getPointer()) : 0; } \ + static Class##Ref null() { Class##Ref c; c.ptr = 0; return c; } \ +protected: \ + Class##Ref() {} \ +public: \ + +#define DEFINE_REF(Class, Base) \ +struct Class##Ref : public Base##Ref \ +{ DEFINE_REF_METHODS(Class, Base) } \ + + +struct ManagedRef { + // Important: Do NOT add a copy constructor to this class or any derived class + // adding a copy constructor actually changes the calling convention, ie. + // is not even binary compatible. Adding it would break assumptions made + // in the jit'ed code. + DEFINE_REF_METHODS(Managed, Managed); + + bool operator==(const ManagedRef &other) { + if (ptr == other.ptr) + return true; + return ptr && other.ptr && ptr->m == other.ptr->m; + } + bool operator!=(const ManagedRef &other) { + return !operator==(other); + } + bool operator!() const { return !ptr || !ptr->managed(); } + + bool isNull() const { return !ptr; } + ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Primitive::undefinedValue().asReturnedValue(); } + +public: + Value *ptr; +}; + } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index 3a4cb3d9e7..e3361ae160 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -422,6 +422,23 @@ inline ReturnedValue value_convert(ExecutionEngine *e, const Value &v) return v.toObject(e->currentContext())->asReturnedValue(); } +struct ObjectRef : public ManagedRef +{ + DEFINE_REF_METHODS(Object, Managed) + + static ObjectRef fromValuePointer(Value *s) { + ObjectRef r; + r.ptr = s; + if (sizeof(void *) == 8) + r.ptr->val = 0; + else + *r.ptr = Value::fromManaged(0); + return r; + } +}; + +DEFINE_REF(ArrayObject, Object); + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index 707bea0c45..e5f693c323 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -46,18 +46,18 @@ using namespace QV4; -ObjectIterator::ObjectIterator(ObjectRef scratch1, ObjectRef scratch2, const ObjectRef o, uint flags) - : object(scratch1) - , current(scratch2) +ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags) + : object(ObjectRef::fromValuePointer(scratch1)) + , current(ObjectRef::fromValuePointer(scratch2)) , arrayNode(0) , arrayIndex(0) , memberIndex(0) , flags(flags) { - object = o; - current = o; + object = o.getPointer(); + current = o.getPointer(); - if (object && object->asArgumentsObject()) { + if (!!object && object->asArgumentsObject()) { Scope scope(object->engine()); Scoped (scope, object->asReturnedValue())->fullyCreate(); } @@ -74,7 +74,7 @@ ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags) object = o; current = o; - if (object && object->asArgumentsObject()) { + if (!!object && object->asArgumentsObject()) { Scope scope(object->engine()); Scoped (scope, object->asReturnedValue())->fullyCreate(); } @@ -103,7 +103,7 @@ void ObjectIterator::next(StringRef name, uint *index, Property *pd, PropertyAtt Object *o = object; bool shadowed = false; while (o != current) { - if ((name && o->hasOwnProperty(name)) || + if ((!!name && o->hasOwnProperty(name)) || (*index != UINT_MAX && o->hasOwnProperty(*index))) { shadowed = true; break; diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h index dafd269590..c87f284288 100644 --- a/src/qml/jsruntime/qv4objectiterator_p.h +++ b/src/qml/jsruntime/qv4objectiterator_p.h @@ -74,7 +74,7 @@ struct Q_QML_EXPORT ObjectIterator uint memberIndex; uint flags; - ObjectIterator(ObjectRef scratch1, ObjectRef scratch2, const ObjectRef o, uint flags); + ObjectIterator(Value *scratch1, Value *scratch2, const ObjectRef o, uint flags); ObjectIterator(Scope &scope, const ObjectRef o, uint flags); void next(StringRef name, uint *index, Property *pd, PropertyAttributes *attributes = 0); ReturnedValue nextPropertyName(ValueRef value); @@ -87,7 +87,7 @@ struct ForEachIteratorObject: Object { Q_MANAGED_TYPE(ForeachIteratorObject) ObjectIterator it; ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o) - : Object(ctx->engine), it(ObjectRef::fromValuePointer(workArea), ObjectRef::fromValuePointer(workArea + 1), + : Object(ctx->engine), it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) { setVTable(staticVTable()); } diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 34cf9ba50d..21f37f3d96 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -84,14 +84,13 @@ public: PersistentValue(ReturnedValue val); template PersistentValue(Returned *obj); - template - PersistentValue(const ManagedRef obj); + PersistentValue(const ManagedRef obj); PersistentValue &operator=(const ValueRef other); + PersistentValue &operator=(const ScopedValue &other); PersistentValue &operator =(ReturnedValue other); template PersistentValue &operator=(Returned *obj); - template - PersistentValue &operator=(const ManagedRef obj); + PersistentValue &operator=(const ManagedRef obj); ~PersistentValue(); ReturnedValue value() const { diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 4645efcbeb..9bc01d12cc 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1702,7 +1702,8 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine) } else if (type == -1 || type == qMetaTypeId()) { QVariant value = *qvariantPtr; QV4::ScopedValue rv(scope, engine->fromVariant(value)); - if (QV4::ManagedRef qobjectWrapper = rv) { + QV4::QObjectWrapperRef qobjectWrapper = rv; + if (!!qobjectWrapper) { if (QObject *object = qobjectWrapper->object()) QQmlData::get(object, true)->setImplicitDestructible(); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 38003eb3c2..ca38c5b0dc 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -200,6 +200,8 @@ private Q_SLOTS: void removeDestroyedObject(QObject*); }; +DEFINE_REF(QObjectWrapper, Object); + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 35ba9bc483..74c8a2d35e 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -80,7 +80,7 @@ RegExpObject::RegExpObject(InternalClass *ic) init(ic->engine); } -RegExpObject::RegExpObject(ExecutionEngine *engine, ManagedRef value, bool global) +RegExpObject::RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global) : Object(engine->regExpClass) , value(value) , global(global) diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index ce3d01725f..1b408749d3 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -84,7 +84,7 @@ struct RegExpObject: Object { Property *lastIndexProperty(ExecutionContext *ctx); bool global; - RegExpObject(ExecutionEngine *engine, ManagedRef value, bool global); + RegExpObject(ExecutionEngine *engine, RegExpRef value, bool global); RegExpObject(ExecutionEngine *engine, const QRegExp &re); ~RegExpObject() {} @@ -101,6 +101,7 @@ protected: static void markObjects(Managed *that, ExecutionEngine *e); }; +DEFINE_REF(RegExp, Object); struct RegExpCtor: FunctionObject { diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 9b9f062a9a..5d471ab4fb 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -379,9 +379,9 @@ struct ScopedCallData { }; -typedef ManagedRef StringRef; -typedef ManagedRef ObjectRef; -typedef ManagedRef FunctionObjectRef; +struct StringRef; +struct ObjectRef; +struct FunctionObjectRef; template inline Scoped::Scoped(const Scope &scope, const ValueRef &v) @@ -485,12 +485,12 @@ inline TypedValue &TypedValue::operator=(Returned *t) return *this; } -template -inline TypedValue &TypedValue::operator =(const ManagedRef &v) -{ - val = v.asReturnedValue(); - return *this; -} +//template +//inline TypedValue &TypedValue::operator =(const ManagedRef &v) +//{ +// val = v.asReturnedValue(); +// return *this; +//} template inline TypedValue &TypedValue::operator=(const TypedValue &t) @@ -517,9 +517,8 @@ PersistentValue::PersistentValue(Returned *obj) { } -template -inline PersistentValue::PersistentValue(const ManagedRef obj) - : d(new PersistentValuePrivate(*obj.ptr)) +inline PersistentValue::PersistentValue(const ManagedRef obj) + : d(new PersistentValuePrivate(obj.asReturnedValue())) { } @@ -529,12 +528,15 @@ inline PersistentValue &PersistentValue::operator=(Returned *obj) return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue()); } -template -inline PersistentValue &PersistentValue::operator=(const ManagedRef obj) +inline PersistentValue &PersistentValue::operator=(const ManagedRef obj) { - return operator=(*obj.ptr); + return operator=(obj.asReturnedValue()); } +inline PersistentValue &PersistentValue::operator=(const ScopedValue &other) +{ + return operator=(other.asReturnedValue()); +} template inline WeakValue::WeakValue(Returned *obj) @@ -572,16 +574,16 @@ inline ValueRef &ValueRef::operator=(const ScopedValue &o) } -template -ManagedRef::ManagedRef(const ScopedValue v) +inline Value *extractValuePointer(const ScopedValue &v) { - ptr = value_cast(*v.ptr) ? v.ptr : 0; + return v.ptr; } template -ManagedRef::ManagedRef(const Scoped &v) - : ptr(v.ptr) -{} +Value *extractValuePointer(const Scoped &v) +{ + return v.ptr; +} struct ScopedProperty { diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index c50b025bc9..7d94195304 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -168,7 +168,7 @@ Script::Script(ExecutionEngine *v4, ObjectRef qml, CompiledData::CompilationUnit Q_ASSERT(vmFunction); Scope valueScope(v4); ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); - compilationUnitHolder = holder; + compilationUnitHolder = holder.asReturnedValue(); } else vmFunction = 0; } @@ -236,7 +236,7 @@ void Script::parse() QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); vmFunction = compilationUnit->linkToEngine(v4); ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); - compilationUnitHolder = holder; + compilationUnitHolder = holder.asReturnedValue(); } if (!vmFunction) { diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index c98147284a..ade64d1352 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -187,6 +187,8 @@ inline ReturnedValue value_convert(ExecutionEngine *e, const Value &v) return v.toString(e)->asReturnedValue(); } +DEFINE_REF(String, Managed); + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 2aefcc4f30..27c81d59a5 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -433,7 +433,7 @@ struct TypedValue : public Value } TypedValue &operator =(T *t); TypedValue &operator =(const Scoped &v); - TypedValue &operator =(const ManagedRef &v); +// TypedValue &operator =(const ManagedRef &v); TypedValue &operator =(Returned *t); TypedValue &operator =(const TypedValue &t); diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h index 6c4a36503b..656608d49b 100644 --- a/src/qml/jsruntime/qv4variantobject_p.h +++ b/src/qml/jsruntime/qv4variantobject_p.h @@ -82,6 +82,8 @@ public: static bool isEqualTo(Managed *m, Managed *other); }; +DEFINE_REF(VariantObject, Object); + struct VariantPrototype : VariantObject { public: diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 48893c1b7f..f9cb9565b3 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1086,7 +1086,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // And, if the new value is a scarce resource, we need to ensure that it does not get // automatically released by the engine until no other references to it exist. QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value)); - if (QV4::ManagedRef v = newv) + QV4::VariantObjectRef v = newv; + if (!!v) v->addVmePropertyReference(); // Write the value and emit change signal as appropriate. -- cgit v1.2.3