aboutsummaryrefslogtreecommitdiffstats
path: root/moth
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2012-12-04 13:40:18 +0100
committerLars Knoll <lars.knoll@digia.com>2012-12-08 04:47:53 +0100
commit5f22fbd7fc4ca6a7f4629cbd34e0fc2e3c1b1cee (patch)
tree31a606540d68674315fbc2c71c76592be2ae3dc8 /moth
parent3b3f3bebcd24073455de9f4abf2f0c7712a1c1ee (diff)
Add a MemoryManager, which does GC for the interpreter.
Todo: - stack walking for MASM - fix all TODOs/FIXMEs and hidden treasures (bugs). Change-Id: I36f8cdc3a545df7287ce1df17b3570a9c017865e Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'moth')
-rw-r--r--moth/moth.pri2
-rw-r--r--moth/qv4mm_moth.cpp81
-rw-r--r--moth/qv4mm_moth.h59
-rw-r--r--moth/qv4vme_moth.cpp43
4 files changed, 169 insertions, 16 deletions
diff --git a/moth/moth.pri b/moth/moth.pri
index 4381c9a53b..160c1aac00 100644
--- a/moth/moth.pri
+++ b/moth/moth.pri
@@ -4,10 +4,12 @@ HEADERS += \
$$PWD/qv4isel_moth_p.h \
$$PWD/qv4instr_moth_p.h \
$$PWD/qv4vme_moth_p.h \
+ $$PWD/qv4mm_moth.h
SOURCES += \
$$PWD/qv4isel_moth.cpp \
$$PWD/qv4instr_moth.cpp \
$$PWD/qv4vme_moth.cpp \
+ $$PWD/qv4mm_moth.cpp
#DEFINES += DO_TRACE_INSTR
diff --git a/moth/qv4mm_moth.cpp b/moth/qv4mm_moth.cpp
new file mode 100644
index 0000000000..44e45fe027
--- /dev/null
+++ b/moth/qv4mm_moth.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmljs_engine.h"
+#include "qv4mm_moth.h"
+
+#include <QList>
+
+using namespace QQmlJS;
+using namespace QQmlJS::Moth;
+
+MemoryManager::MemoryManager()
+{
+ stackFrames.reserve(64);
+}
+
+MemoryManager::~MemoryManager()
+{
+}
+
+VM::Value *MemoryManager::allocStackFrame(std::size_t frameSize)
+{
+ std::size_t size = frameSize * sizeof(VM::Value);
+ MMObject *m = alloc(align(size));
+ stackFrames.append(m);
+ return reinterpret_cast<VM::Value *>(&m->data);
+}
+
+void MemoryManager::deallocStackFrame(VM::Value *stackFrame)
+{
+ MMObject *o = toObject(stackFrame);
+ for (int i = stackFrames.size() - 1; i >= 0; --i) {
+ if (stackFrames[i] == o) {
+ stackFrames.remove(i);
+ dealloc(o);
+ return;
+ }
+ }
+
+ Q_UNREACHABLE();
+}
+
+void MemoryManager::collectRootsOnStack(QVector<VM::Object *> &roots) const
+{
+ for (int i = 0, ei = stackFrames.size(); i < ei; ++i) {
+ MMObject *m = stackFrames[i];
+ VM::Value *frame = reinterpret_cast<VM::Value *>(&m->data);
+ std::size_t frameSize = (m->info.size - align(sizeof(MMInfo))) / sizeof(VM::Value);
+ for (std::size_t j = 0; j < frameSize; ++j) {
+ if (VM::Object *o = frame[j].asObject()) {
+ roots.append(o);
+ }
+ }
+ }
+}
diff --git a/moth/qv4mm_moth.h b/moth/qv4mm_moth.h
new file mode 100644
index 0000000000..a2b1ebd556
--- /dev/null
+++ b/moth/qv4mm_moth.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QV4GC_MOTH_H
+#define QV4GC_MOTH_H
+
+#include "qv4mm.h"
+
+#include <QVector>
+
+namespace QQmlJS {
+namespace Moth {
+
+class MemoryManager: public QQmlJS::VM::MemoryManager
+{
+public:
+ MemoryManager();
+ ~MemoryManager();
+
+ VM::Value *allocStackFrame(std::size_t frameSize);
+ void deallocStackFrame(VM::Value *stackFrame);
+
+protected:
+ virtual void collectRootsOnStack(QVector<VM::Object *> &roots) const;
+
+private:
+ QVector<MMObject *> stackFrames;
+};
+
+} // namespace Moth
+} // namespace QQmlJS
+
+#endif // QV4GC_MOTH_H
diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp
index d38d7d7cb7..86b396f422 100644
--- a/moth/qv4vme_moth.cpp
+++ b/moth/qv4vme_moth.cpp
@@ -2,6 +2,7 @@
#include "qv4instr_moth_p.h"
#include "qmljs_value.h"
#include "debugging.h"
+#include "qv4mm_moth.h"
#include <iostream>
@@ -51,7 +52,7 @@ using namespace QQmlJS::Moth;
#endif
-static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVector<VM::Value> &stack, int index)
+static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, VM::Value* stack, int index)
{
#ifdef DO_TRACE_INSTR
const char *kind;
@@ -87,25 +88,32 @@ static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVecto
int off = index - context->variableCount();
Q_ASSERT(off >= 0);
- Q_ASSERT(off < stack.size());
- return stack.data() + off;
+ return stack + off;
}
}
class FunctionState: public Debugging::FunctionState
{
public:
- FunctionState(QQmlJS::VM::ExecutionContext *context, QVector<VM::Value> *stack, const uchar **code)
+ FunctionState(QQmlJS::VM::ExecutionContext *context, const uchar **code)
: Debugging::FunctionState(context)
- , stack(stack)
+ , stack(0)
+ , stackSize(0)
, code(code)
{}
- virtual VM::Value *temp(unsigned idx) { return stack->data() + idx; }
+ ~FunctionState()
+ { if (stack) static_cast<MemoryManager *>(context()->engine->memoryManager)->deallocStackFrame(stack); }
+
+ virtual VM::Value *temp(unsigned idx) { return stack + idx; }
+
+ void setStack(VM::Value *stack, unsigned stackSize)
+ { this->stack = stack; this->stackSize = stackSize; }
private:
- QVector<VM::Value> *stack;
+ VM::Value *stack;
+ unsigned stackSize;
const uchar **code;
};
@@ -130,8 +138,9 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
}
#endif
- QVector<VM::Value> stack;
- FunctionState state(context, &stack, &code);
+ VM::Value *stack = 0;
+ unsigned stackSize = 0;
+ FunctionState state(context, &code);
#ifdef MOTH_THREADED_INTERPRETER
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
@@ -191,7 +200,9 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
- stack.resize(instr.value);
+ stackSize = instr.value;
+ stack = static_cast<MemoryManager *>(context->engine->memoryManager)->allocStackFrame(stackSize);
+ state.setStack(stack, stackSize);
MOTH_END_INSTR(Push)
MOTH_BEGIN_INSTR(CallValue)
@@ -207,20 +218,20 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
#endif // DO_TRACE_INSTR
quint32 argStart = instr.args - context->variableCount();
TRACE(Call, "value index = %d, argStart = %d, argc = %d, result temp index = %d", instr.destIndex, argStart, instr.argc, instr.targetTempIndex);
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
TEMP(instr.targetTempIndex) = __qmljs_call_value(context, VM::Value::undefinedValue(), TEMP(instr.destIndex), args, instr.argc);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
quint32 argStart = instr.args - context->variableCount();
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
VM::Value base = TEMP(instr.baseTemp);
TEMP(instr.targetTempIndex) = __qmljs_call_property(context, base, instr.name, args, instr.argc);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallBuiltin)
quint32 argStart = instr.args - context->variableCount();
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
void *buf;
switch (instr.builtin) {
case Instr::instr_callBuiltin::builtin_typeof:
@@ -300,20 +311,20 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
MOTH_BEGIN_INSTR(CreateValue)
quint32 argStart = instr.args - context->variableCount();
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_value(context, TEMP(instr.func), args, instr.argc);
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
quint32 argStart = instr.args - context->variableCount();
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_property(context, TEMP(instr.base), instr.name, args, instr.argc);
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, argc = %d", instr.name->toQString().toUtf8().constData(), instr.argc);
quint32 argStart = instr.args - context->variableCount();
- VM::Value *args = stack.data() + argStart;
+ VM::Value *args = stack + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
MOTH_END_INSTR(CreateActivationProperty)