aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-08-09 16:45:02 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-08-12 13:29:27 +0200
commit7c2adbbb6cccefd202164049dc9144b4d13aec0a (patch)
tree7410500f53aac1b8fe2a46729db48732744ebf4b /src/qml
parent42dc821dd68cc63aa8300f2678639dbaacda1057 (diff)
Add reference counting to the VM functions
This reduces memory pressure, keep engine->functions small and thus makes back trace lookup faster. It became visible for example in the QtQuickControls auto-tests that use plenty of loaders and we ended up with 30k+ functions. Change-Id: Iaa5981f44e1e49ad9417a50c1e6a74946090dd28 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qv4isel_p.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4function.cpp10
-rw-r--r--src/qml/jsruntime/qv4function_p.h18
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h3
-rw-r--r--src/qml/jsruntime/qv4script.cpp8
-rw-r--r--src/qml/jsruntime/qv4script_p.h1
8 files changed, 47 insertions, 7 deletions
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 03c0ee750e..c864378844 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -90,7 +90,7 @@ QV4::Function *EvalInstructionSelection::createFunctionMapping(QV4::Function *ou
vmFunction->sourceFile = irFunction->sourceFile;
if (outer)
- outer->nestedFunctions.append(vmFunction);
+ outer->addNestedFunction(vmFunction);
foreach (const QString *formal, irFunction->formals)
if (formal)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 0b7c850aa6..acc6d9e132 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -96,7 +96,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
-#ifdef V4_ENABLE_JIT
+#if 0
factory = new QQmlJS::MASM::ISelFactory;
#else // !V4_ENABLE_JIT
factory = new QQmlJS::Moth::ISelFactory;
@@ -280,7 +280,6 @@ ExecutionEngine::~ExecutionEngine()
delete bumperPointerAllocator;
delete regExpCache;
UnwindHelper::deregisterFunctions(functions);
- qDeleteAll(functions);
delete regExpAllocator;
delete executableAllocator;
}
@@ -379,7 +378,7 @@ ExecutionContext *ExecutionEngine::pushGlobalContext()
Function *ExecutionEngine::newFunction(const QString &name)
{
- Function *f = new Function(newIdentifier(name));
+ Function *f = new Function(this, newIdentifier(name));
functions.append(f);
functionsNeedSort = true;
return f;
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index bf633a9b41..8c303a21ab 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -43,6 +43,9 @@
#include "qv4managed_p.h"
#include "qv4string_p.h"
#include "qv4value_p.h"
+#include "qv4engine_p.h"
+#include "qv4lookup_p.h"
+#include "qv4unwindhelper_p.h"
QT_BEGIN_NAMESPACE
@@ -50,7 +53,14 @@ using namespace QV4;
Function::~Function()
{
+ engine->functions.remove(engine->functions.indexOf(this));
+ UnwindHelper::deregisterFunction(this);
+
+ Q_ASSERT(!refCount);
delete[] codeData;
+ delete[] lookups;
+ foreach (Function *f, nestedFunctions)
+ f->deref();
}
void Function::mark()
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 3ff31ed2e3..612bbb122e 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -87,6 +87,7 @@ struct LineNumberMapping
};
struct Function {
+ int refCount;
String *name;
Value (*code)(ExecutionContext *, const uchar *);
@@ -111,8 +112,11 @@ struct Function {
QString sourceFile;
QVector<LineNumberMapping> lineNumberMappings;
- Function(String *name)
- : name(name)
+ ExecutionEngine *engine;
+
+ Function(ExecutionEngine *engine, String *name)
+ : refCount(0)
+ , name(name)
, code(0)
, codeData(0)
, codeSize(0)
@@ -122,9 +126,19 @@ struct Function {
, usesArgumentsObject(false)
, isStrict(false)
, isNamedExpression(false)
+ , engine(engine)
{}
~Function();
+ void ref() { ++refCount; }
+ void deref() { if (!--refCount) delete this; }
+
+ void addNestedFunction(Function *f)
+ {
+ f->ref();
+ nestedFunctions.append(f);
+ }
+
inline bool needsActivation() const { return hasNestedFunctions || hasDirectEval || usesArgumentsObject; }
void mark();
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index ffdd08ed0a..e441b1cf0e 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -93,6 +93,12 @@ FunctionObject::FunctionObject(ExecutionContext *scope, String *name)
defineReadonlyProperty(scope->engine->id_name, Value::fromString(name));
}
+FunctionObject::~FunctionObject()
+{
+ if (function)
+ function->deref();
+}
+
Value FunctionObject::newInstance()
{
return construct(0, 0);
@@ -318,6 +324,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
{
vtbl = &static_vtbl;
this->function = function;
+ this->function->ref();
assert(function);
assert(function->code);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 8465142616..71691ba1c4 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -108,6 +108,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
Function *function;
FunctionObject(ExecutionContext *scope, String *name = 0);
+ ~FunctionObject();
Value newInstance();
@@ -124,6 +125,8 @@ protected:
static const ManagedVTable static_vtbl;
static void markObjects(Managed *that);
static bool hasInstance(Managed *that, const Value &value);
+ static void destroy(Managed *that)
+ { static_cast<FunctionObject*>(that)->~FunctionObject(); }
};
struct FunctionCtor: FunctionObject
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 3de218a451..8521501e57 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -67,6 +67,7 @@ struct QmlBindingWrapper : FunctionObject
{
vtbl = &static_vtbl;
function = f;
+ function->ref();
usesArgumentsObject = function->usesArgumentsObject;
needsActivation = function->needsActivation();
defineReadonlyProperty(scope->engine->id_length, Value::fromInt32(1));
@@ -112,6 +113,10 @@ Value QmlBindingWrapper::call(Managed *that, const Value &, Value *, int)
}
+Script::~Script()
+{
+}
+
void Script::parse()
{
if (parsed)
@@ -174,8 +179,9 @@ void Script::parse()
QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(v4, &module));
if (inheritContext)
isel->setUseFastLookups(false);
- if (globalIRCode)
+ if (globalIRCode) {
vmFunction = isel->vmFunction(globalIRCode);
+ }
}
if (!vmFunction)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 274a87db26..20f9285879 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -59,6 +59,7 @@ struct Q_QML_EXPORT Script {
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false)
, qml(Value::fromObject(qml)), vmFunction(0), parseAsBinding(true) {}
+ ~Script();
QString sourceFile;
int line;
int column;