protected:
Managed()
- : markBit(0)
- , inUse(1)
- , extensible(1)
- , isNonStrictArgumentsObject(0)
- , isBuiltinFunction(0)
- , needsActivation(0)
- , usesArgumentsObject(0)
- , strictMode(0)
- , type(Type_Invalid)
- , subtype(0)
- , stringIdentifier(0)
-#if CPU(X86_64)
- , unused(0)
-#endif
- {}
+ : _data(0)
+ { inUse = 1; extensible = 1; }
virtual ~Managed();
public:
QString className() const;
+ Managed **nextFreeRef() {
+ return reinterpret_cast<Managed **>(this);
+ }
+ Managed *nextFree() {
+ return *reinterpret_cast<Managed **>(this);
+ }
+ void setNextFree(Managed *m) {
+ *reinterpret_cast<Managed **>(this) = m;
+ }
+
protected:
virtual void markObjects() {}
union {
- Managed *nextFree;
+ uint _data;
struct {
- quintptr markBit : 1;
- quintptr inUse : 1;
- quintptr extensible : 1; // used by Object
- quintptr isNonStrictArgumentsObject : 1;
- quintptr isBuiltinFunction : 1; // used by FunctionObject
- quintptr needsActivation : 1; // used by FunctionObject
- quintptr usesArgumentsObject : 1; // used by FunctionObject
- quintptr strictMode : 1; // used by FunctionObject
- quintptr type : 5;
- mutable quintptr subtype : 3;
- mutable quintptr stringIdentifier : 16;
-#if CPU(X86_64)
- quintptr unused : 32;
-#endif
+ uint markBit : 1;
+ uint inUse : 1;
+ uint extensible : 1; // used by Object
+ uint isNonStrictArgumentsObject : 1;
+ uint isBuiltinFunction : 1; // used by FunctionObject
+ uint needsActivation : 1; // used by FunctionObject
+ uint usesArgumentsObject : 1; // used by FunctionObject
+ uint strictMode : 1; // used by FunctionObject
+ uint type : 5;
+ mutable uint subtype : 3;
+ uint unused : 16;
};
};
}
};
+#define SCRIBBLE(obj, c, size) \
+ if (m_d->scribble) \
+ ::memset((void *)(obj + 1), c, size - sizeof(Managed));
+
+
namespace QQmlJS { namespace VM {
bool operator<(const MemoryManager::Data::Chunk &a, const MemoryManager::Data::Chunk &b)
Managed **last = &m_d->smallItems[pos];
while (chunk <= end) {
Managed *o = reinterpret_cast<Managed *>(chunk);
- o->inUse = 0;
- o->markBit = 0;
+ o->_data = 0;
*last = o;
- last = &o->nextFree;
+ last = o->nextFreeRef();
chunk += size;
}
*last = 0;
}
found:
- m_d->smallItems[pos] = m->nextFree;
+ m_d->smallItems[pos] = m->nextFree();
return m;
}
-#define SCRIBBLE(obj, c, size) \
- if (m_d->scribble) \
- ::memset((void *)(obj + 1), c, size - sizeof(Managed));
-
void MemoryManager::mark()
{
m_d->engine->markObjects();
for (QHash<Managed *, uint>::const_iterator it = m_d->protectedObject.begin(); it != m_d->protectedObject.constEnd(); ++it)
it.key()->mark();
+#if CPU(X86_64)
+ // push all caller saved registers to the stack, so we can find the objects living in these registers
+ quintptr regs[5];
+ asm(
+ "mov %%rbp, %0\n"
+ "mov %%r12, %1\n"
+ "mov %%r13, %2\n"
+ "mov %%r14, %3\n"
+ "mov %%r15, %4\n"
+ : "=m" (regs[0]), "=m" (regs[1]), "=m" (regs[2]), "=m" (regs[3]), "=m" (regs[4])
+ :
+ :
+ );
+#endif
collectFromStack();
return;
Managed **f = &m_d->smallItems[size >> 4];
- for (char *chunk = chunkStart, *chunkEnd = chunk + chunkSize - size; chunk <= chunkEnd; ) {
+ for (char *chunk = chunkStart, *chunkEnd = chunk + chunkSize - size; chunk <= chunkEnd; chunk += size) {
Managed *m = reinterpret_cast<Managed *>(chunk);
// qDebug("chunk @ %p, size = %lu, in use: %s, mark bit: %s",
// chunk, m->size, (m->inUse ? "yes" : "no"), (m->markBit ? "true" : "false"));
assert((intptr_t) chunk % 16 == 0);
- chunk = chunk + size;
if (m->inUse) {
if (m->markBit) {
m->markBit = 0;
} else {
-// qDebug() << "-- collecting it." << m << *f << &m->nextFree;
+// qDebug() << "-- collecting it." << m << *f << m->nextFree();
m->~Managed();
- m->nextFree = *f;
- f = &m->nextFree;
+ m->setNextFree(*f);
+ *f = m;
SCRIBBLE(m, 0x99, size);
++freedCount;
}
// qDebug() << "stack:" << hex << stackTop << stackSize << (stackTop + stackSize);
quintptr *current = (&valueOnStack) + 1;
-// qDebug() << "collectFromStack" << top << current << &valueOnStack;
+// qDebug() << "collectFromStack";// << top << current << &valueOnStack;
char** heapChunkBoundaries = (char**)alloca(m_d->heapChunks.count() * 2 * sizeof(char*));
char** heapChunkBoundariesEnd = heapChunkBoundaries + 2 * m_d->heapChunks.count();
heapChunkBoundaries[i++] = reinterpret_cast<char*>(it->memory.base());
heapChunkBoundaries[i++] = reinterpret_cast<char*>(it->memory.base()) + it->memory.size() - it->chunkSize;
}
+ assert(i == m_d->heapChunks.count() * 2);
for (; current < top; ++current) {
char* genericPtr =
reinterpret_cast<char *>(*current);
#endif
- if (genericPtr < *heapChunkBoundaries || genericPtr > *heapChunkBoundariesEnd)
+ if (genericPtr < *heapChunkBoundaries || genericPtr > *(heapChunkBoundariesEnd - 1))
continue;
int index = qLowerBound(heapChunkBoundaries, heapChunkBoundariesEnd, genericPtr) - heapChunkBoundaries;
// An odd index means the pointer is _before_ the end of a heap chunk and therefore valid.
+ assert(index >= 0 && index < m_d->heapChunks.count() * 2);
if (index & 1) {
int size = m_d->heapChunks.at(index >> 1).chunkSize;
Managed *m = reinterpret_cast<Managed *>(genericPtr);
-// qDebug() << " inside" << size << m;
+// qDebug() << " inside" << size;
if (((quintptr)m - (quintptr)heapChunkBoundaries[index-1]) % size)
// wrongly aligned value, skip it
// Skip pointers to already freed objects, they are bogus as well
continue;
- m->mark();
// qDebug() << " marking";
+ m->mark();
}
}
}