(classname::func == QV4::Managed::func ? 0 : classname::func)
-struct GCDeletable
-{
- GCDeletable() : next(0), lastCall(false) {}
- virtual ~GCDeletable() {}
- GCDeletable *next;
- bool lastCall;
-};
-
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
{ \
parentVTable, \
QV4::Object::markObjects(that, e);
}
-namespace {
- struct QObjectDeleter : public QV4::GCDeletable
- {
- QObjectDeleter(QObject *o)
- : m_objectToDelete(o)
- {}
- ~QObjectDeleter()
- {
- QQmlData *ddata = QQmlData::get(m_objectToDelete, false);
- if (ddata && ddata->ownContext && ddata->context)
- ddata->context->emitDestruction();
- // This object is notionally destroyed now
- ddata->isQueuedForDeletion = true;
- if (lastCall)
- delete m_objectToDelete;
- else
- m_objectToDelete->deleteLater();
- }
-
- QObject *m_objectToDelete;
- };
-}
-
-void QObjectWrapper::destroy(Heap::Base *that)
+void QObjectWrapper::destroyObject(bool lastCall)
{
- Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
- QPointer<QObject> object = This->object;
- ExecutionEngine *engine = This->internalClass->engine;
- This->~Data();
- This = 0;
- if (!object)
- return;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (!ddata)
- return;
-
- if (object->parent() || ddata->indestructible)
- return;
+ Heap::QObjectWrapper *h = d();
+ if (!h->internalClass)
+ return; // destroyObject already got called
+
+ QPointer<QObject> object = h->object;
+ if (object) {
+ QQmlData *ddata = QQmlData::get(object, false);
+ if (ddata) {
+ if (!object->parent() && !ddata->indestructible) {
+ if (ddata && ddata->ownContext && ddata->context)
+ ddata->context->emitDestruction();
+ // This object is notionally destroyed now
+ ddata->isQueuedForDeletion = true;
+ if (lastCall)
+ delete object;
+ else
+ object->deleteLater();
+ }
+ }
+ }
- QObjectDeleter *deleter = new QObjectDeleter(object);
- engine->memoryManager->registerDeletable(deleter);
+ h->internalClass = 0;
+ h->~Data();
}
static void setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value);
void setProperty(ExecutionEngine *engine, int propertyIndex, const Value &value);
+ void destroyObject(bool lastCall);
+
protected:
static bool isEqualTo(Managed *that, Managed *o);
static PropertyAttributes query(const Managed *, String *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
- static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
LargeItem *largeItems;
std::size_t totalLargeItemsAllocated;
- GCDeletable *deletable;
-
// statistics:
#ifdef DETAILED_MM_STATS
QVector<unsigned> allocSizeCounters;
, maxChunkSize(32*1024)
, largeItems(0)
, totalLargeItemsAllocated(0)
- , deletable(0)
{
memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
if ((*it).managed()->d()->vtable() != QObjectWrapper::staticVTable())
continue;
QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
- if (!qobjectWrapper)
- continue;
QObject *qobject = qobjectWrapper->object();
if (!qobject)
continue;
void MemoryManager::sweep(bool lastSweep)
{
- if (m_weakValues) {
- for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
- if (Managed *m = (*it).as<Managed>()) {
- if (!m->markBit())
- (*it) = Primitive::undefinedValue();
- }
+ for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) {
+ if (!(*it).isManaged())
+ continue;
+ Managed *m = (*it).as<Managed>();
+ if (m->markBit())
+ continue;
+ // we need to call detroyObject on qobjectwrappers now, so that they can emit the destroyed
+ // signal before we start sweeping the heap
+ if ((*it).managed()->d()->vtable() == QObjectWrapper::staticVTable()) {
+ QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed());
+ qobjectWrapper->destroyObject(lastSweep);
}
+
+ (*it) = Primitive::undefinedValue();
}
if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) {
i = *last;
}
- GCDeletable *deletable = m_d->deletable;
- m_d->deletable = 0;
- while (deletable) {
- GCDeletable *next = deletable->next;
- deletable->lastCall = lastSweep;
- delete deletable;
- deletable = next;
- }
-
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
Heap::ExecutionContext *ctx = engine()->current;
MemoryManager::~MemoryManager()
{
delete m_persistentValues;
- delete m_weakValues;
- m_weakValues = 0;
sweep(/*lastSweep*/true);
+
+ delete m_weakValues;
#ifdef V4_USE_VALGRIND
VALGRIND_DESTROY_MEMPOOL(this);
#endif
#endif // DETAILED_MM_STATS
}
-void MemoryManager::registerDeletable(GCDeletable *d)
-{
- d->next = m_d->deletable;
- m_d->deletable = d;
-}
-
#ifdef DETAILED_MM_STATS
void MemoryManager::willAllocate(std::size_t size)
{
void dumpStats() const;
- void registerDeletable(GCDeletable *d);
-
size_t getUsedMem() const;
size_t getAllocatedMem() const;
size_t getLargeItemsMem() const;