Cleanups to property allocation in the VMEMO

There's no need for a separate propertiesAllocated bool,
we can keep that state in the WeakValue itself.

Change-Id: Ife0f517bee9bc5830680eec68983767379a3c2cf
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
This commit is contained in:
Lars Knoll 2015-09-16 15:30:51 +02:00 committed by Simon Hausmann
parent 10a712eb98
commit f01bfcf8ed
3 changed files with 26 additions and 31 deletions

View File

@ -63,17 +63,18 @@ QQmlVMEVariantQObjectPtr::~QQmlVMEVariantQObjectPtr()
void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
{ {
if (m_target && m_index >= 0) { if (!m_target || QQmlData::wasDeleted(m_target->object))
if (m_target->propertiesInitialized && !m_target->properties.isUndefined()) { return;
QV4::ExecutionEngine *v4 = m_target->cache->engine;
if (m_index >= 0) {
QV4::ExecutionEngine *v4 = m_target->properties.engine();
if (v4) { if (v4) {
QV4::Scope scope(v4); QV4::Scope scope(v4);
QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value()); QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
if (sp)
*(sp->data() + m_index) = QV4::Primitive::nullValue(); *(sp->data() + m_index) = QV4::Primitive::nullValue();
} }
}
if (!QQmlData::wasDeleted(m_target->object))
m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0); m_target->activate(m_target->object, m_target->methodOffset() + m_index, 0);
} }
} }
@ -148,10 +149,10 @@ QAbstractDynamicMetaObject *QQmlVMEMetaObject::toDynamicMetaObject(QObject *o)
QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
QQmlPropertyCache *cache, QQmlPropertyCache *cache,
const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData) const QQmlVMEMetaData *meta, QV4::ExecutionContext *qmlBindingContext, QQmlCompiledData *compiledData)
: object(obj), : object(obj),
ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta), ctxt(QQmlData::get(obj, true)->outerContext), cache(cache), metaData(meta),
hasAssignedMetaObjectData(false), aliasEndpoints(0), hasAssignedMetaObjectData(false), aliasEndpoints(0),
propertiesInitialized(false), interceptors(0), methods(0) interceptors(0), methods(0)
{ {
QObjectPrivate *op = QObjectPrivate::get(obj); QObjectPrivate *op = QObjectPrivate::get(obj);
@ -215,8 +216,15 @@ QQmlVMEMetaObject::~QQmlVMEMetaObject()
QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData() QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
{ {
if (!ensurePropertiesAllocated()) if (properties.isUndefined()) {
if (properties.valueRef())
// in some situations, the QObject wrapper (and associated data,
// such as the varProperties array) will have been cleaned up, but the
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
// In this situation, return 0.
return 0; return 0;
allocateProperties();
}
return static_cast<QV4::MemberData*>(properties.asManaged()); return static_cast<QV4::MemberData*>(properties.asManaged());
} }
@ -1050,19 +1058,6 @@ void QQmlVMEMetaObject::setVMEProperty(int index, const QV4::Value &v)
return writeVarProperty(index - propOffset(), v); return writeVarProperty(index - propOffset(), v);
} }
bool QQmlVMEMetaObject::ensurePropertiesAllocated()
{
if (!propertiesInitialized)
allocateProperties();
// in some situations, the QObject's v8object (and associated v8 data,
// such as the varProperties array) will have been cleaned up, but the
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
// In this situation, the varProperties handle will be (and should remain)
// empty.
return !properties.isUndefined();
}
void QQmlVMEMetaObject::ensureQObjectWrapper() void QQmlVMEMetaObject::ensureQObjectWrapper()
{ {
Q_ASSERT(cache && cache->engine); Q_ASSERT(cache && cache->engine);
@ -1085,12 +1080,12 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
void QQmlVMEMetaObject::allocateProperties() void QQmlVMEMetaObject::allocateProperties()
{ {
Q_ASSERT(cache && cache->engine); Q_ASSERT(cache && cache->engine);
Q_ASSERT(!properties.valueRef());
QV4::ExecutionEngine *v4 = cache->engine; QV4::ExecutionEngine *v4 = cache->engine;
QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount); QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount);
properties.set(v4, data); properties.set(v4, data);
for (uint i = 0; i < data->size; ++i) for (uint i = 0; i < data->size; ++i)
data->data[i] = QV4::Encode::undefined(); data->data[i] = QV4::Encode::undefined();
propertiesInitialized = true;
} }
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const

View File

@ -201,9 +201,7 @@ public:
QQmlVMEMetaObjectEndpoint *aliasEndpoints; QQmlVMEMetaObjectEndpoint *aliasEndpoints;
QV4::WeakValue properties; QV4::WeakValue properties;
bool propertiesInitialized;
inline void allocateProperties(); inline void allocateProperties();
inline bool ensurePropertiesAllocated();
QV4::MemberData *propertiesAsMemberData(); QV4::MemberData *propertiesAsMemberData();
int readPropertyAsInt(int id); int readPropertyAsInt(int id);

View File

@ -7119,6 +7119,7 @@ void tst_qqmlecmascript::onDestruction()
QObject *obj = c.create(); QObject *obj = c.create();
QVERIFY(obj != 0); QVERIFY(obj != 0);
delete obj; delete obj;
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
} }
{ {
@ -7130,6 +7131,7 @@ void tst_qqmlecmascript::onDestruction()
QQmlComponent c(&engine, testFileUrl("onDestruction.qml")); QQmlComponent c(&engine, testFileUrl("onDestruction.qml"));
QObject *obj = c.create(); QObject *obj = c.create();
QVERIFY(obj != 0); QVERIFY(obj != 0);
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
} }
} }