aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine_p.h6
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h8
-rw-r--r--src/qml/jsruntime/qv4managed_p.h2
-rw-r--r--src/qml/jsruntime/qv4mm.cpp33
-rw-r--r--src/qml/jsruntime/qv4value_p.h34
6 files changed, 57 insertions, 32 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 6dd33d3f47..4f8f329e2b 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -914,9 +914,9 @@ void ExecutionEngine::markObjects()
Heap::ExecutionContext *c = currentContext();
while (c) {
Q_ASSERT(c->inUse());
- if (!c->markBit) {
- c->markBit = 1;
- c->internalClass->vtable->markObjects(c, this);
+ if (!c->isMarked()) {
+ c->setMarkBit();
+ c->gcGetInternalClass()->vtable->markObjects(c, this);
}
c = c->parent;
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 017b2a8c52..8b813ea598 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -403,7 +403,7 @@ void Managed::mark(QV4::ExecutionEngine *engine)
Q_ASSERT(inUse());
if (markBit())
return;
- d()->markBit = 1;
+ d()->setMarkBit();
engine->pushForGC(d());
}
@@ -412,9 +412,9 @@ inline
void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
- if (markBit)
+ if (isMarked())
return;
- markBit = 1;
+ setMarkBit();
engine->pushForGC(this);
}
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index fe88584c2e..5d29d44dc0 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -77,11 +77,11 @@ public:
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
Heap::String *entry = entries[i];
- if (!entry || entry->markBit)
+ if (!entry || entry->isMarked())
continue;
- entry->markBit = 1;
- Q_ASSERT(entry->internalClass->vtable->markObjects);
- entry->internalClass->vtable->markObjects(entry, e);
+ entry->setMarkBit();
+ Q_ASSERT(entry->gcGetInternalClass()->vtable->markObjects);
+ entry->gcGetInternalClass()->vtable->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 27a601ee13..fad3b85b2e 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -291,7 +291,7 @@ public:
void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
bool inUse() const { return d()->inUse(); }
- bool markBit() const { return d()->markBit; }
+ bool markBit() const { return d()->isMarked(); }
static void destroy(Heap::Base *) {}
private:
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index ff84e47ef9..4ddb544cba 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -188,9 +188,9 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa
Q_ASSERT((qintptr) item % 16 == 0);
- if (m->markBit) {
+ if (m->isMarked()) {
Q_ASSERT(m->inUse());
- m->markBit = 0;
+ m->clearMarkBit();
sweepData->isEmpty = false;
++(*itemsInUse);
} else {
@@ -199,8 +199,8 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa
#ifdef V4_USE_VALGRIND
VALGRIND_ENABLE_ERROR_REPORTING;
#endif
- if (m->internalClass->vtable->destroy)
- m->internalClass->vtable->destroy(m);
+ if (m->gcGetInternalClass()->vtable->destroy)
+ m->gcGetInternalClass()->vtable->destroy(m);
memset(m, 0, itemSize);
#ifdef V4_USE_VALGRIND
@@ -326,8 +326,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
Heap::Base *h = engine->popForGC();
- Q_ASSERT (h->internalClass->vtable->markObjects);
- h->internalClass->vtable->markObjects(h, engine);
+ Q_ASSERT (h->gcGetInternalClass()->vtable->markObjects);
+ h->gcGetInternalClass()->vtable->markObjects(h, engine);
}
}
@@ -364,7 +364,9 @@ void MemoryManager::mark()
for (PersistentValuePrivate *weak = m_weakValues; weak; weak = weak->next) {
if (!weak->refcount || !weak->value.isManaged())
continue;
- QObjectWrapper *qobjectWrapper = weak->value.managed()->as<QObjectWrapper>();
+ if (weak->value.asManaged()->d()->gcGetInternalClass()->vtable != QObjectWrapper::staticVTable())
+ continue;
+ QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>(weak->value.managed());
if (!qobjectWrapper)
continue;
QObject *qobject = qobjectWrapper->object();
@@ -481,14 +483,14 @@ void MemoryManager::sweep(bool lastSweep)
while (i) {
Heap::Base *m = i->heapObject();
Q_ASSERT(m->inUse());
- if (m->markBit) {
- m->markBit = 0;
+ if (m->isMarked()) {
+ m->clearMarkBit();
last = &i->next;
i = i->next;
continue;
}
- if (m->internalClass->vtable->destroy)
- m->internalClass->vtable->destroy(m);
+ if (m->gcGetInternalClass()->vtable->destroy)
+ m->gcGetInternalClass()->vtable->destroy(m);
*last = i->next;
free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
@@ -504,6 +506,15 @@ void MemoryManager::sweep(bool 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;
+ while (ctx) {
+ ctx->clearMarkBit();
+ ctx = ctx->parent;
+ }
+ }
}
bool MemoryManager::isGCBlocked() const
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 12e81d4f30..31db8a21c5 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -50,15 +50,18 @@ struct Q_QML_EXPORT Base {
Base() {}
Base(InternalClass *internal)
: internalClass(internal)
- , markBit(0)
, extensible(1)
{
+ Q_ASSERT(inUse() && !isMarked());
// ####
// Q_ASSERT(internal && internal->vtable);
}
- InternalClass *internalClass;
+ union {
+ InternalClass *internalClass;
+ quintptr mm_data;
+ };
struct {
- uchar markBit : 1;
+ uchar _markBit : 1;
uchar _inUse : 1;
uchar extensible : 1; // used by Object
uchar _needsActivation : 1; // used by FunctionObject
@@ -76,23 +79,34 @@ struct Q_QML_EXPORT Base {
inline ReturnedValue asReturnedValue() const;
inline void mark(QV4::ExecutionEngine *engine);
- inline bool isMarked() const {
- return markBit;
- }
-
enum {
+ MarkBit = 0x1,
NotInUse = 0x2,
PointerMask = ~0x3
};
+
+ InternalClass *gcGetInternalClass() const {
+ return reinterpret_cast<InternalClass *>(mm_data & PointerMask);
+ }
+ inline bool isMarked() const {
+ return mm_data & MarkBit;
+ }
+ inline void setMarkBit() {
+ mm_data |= MarkBit;
+ }
+ inline void clearMarkBit() {
+ mm_data &= ~MarkBit;
+ }
+
inline bool inUse() const {
- return !((quintptr)internalClass & NotInUse);
+ return !(mm_data & NotInUse);
}
Base *nextFree() {
- return reinterpret_cast<Base *>(reinterpret_cast<quintptr>(internalClass) & PointerMask);
+ return reinterpret_cast<Base *>(mm_data & PointerMask);
}
void setNextFree(Base *m) {
- internalClass = reinterpret_cast<InternalClass *>(reinterpret_cast<quintptr>(m) | NotInUse);
+ mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
}
void *operator new(size_t, Managed *m) { return m; }