diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2012-12-04 13:40:18 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@digia.com> | 2012-12-08 04:47:53 +0100 |
commit | 5f22fbd7fc4ca6a7f4629cbd34e0fc2e3c1b1cee (patch) | |
tree | 31a606540d68674315fbc2c71c76592be2ae3dc8 /moth | |
parent | 3b3f3bebcd24073455de9f4abf2f0c7712a1c1ee (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.pri | 2 | ||||
-rw-r--r-- | moth/qv4mm_moth.cpp | 81 | ||||
-rw-r--r-- | moth/qv4mm_moth.h | 59 | ||||
-rw-r--r-- | moth/qv4vme_moth.cpp | 43 |
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) |