Reduce memory consumption of FunctionObject
authorLars Knoll <lars.knoll@digia.com>
Mon, 3 Mar 2014 20:00:30 +0000 (21:00 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 7 Mar 2014 15:55:12 +0000 (16:55 +0100)
Remove varCount and formalParameterCount members
in FunctionObject and retrieve them from the
CompiledFunction instead.

Change-Id: I8a6cdc6d354b0f33da9d67a4c3dbfe8a7cc96176
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4script.cpp

index 5dedd59..1f28219 100644 (file)
@@ -89,7 +89,7 @@ void ArgumentsObject::fullyCreate()
     if (fullyCreated)
         return;
 
-    uint numAccessors = qMin((int)context->function->formalParameterCount, context->realArgumentCount);
+    uint numAccessors = qMin((int)context->function->formalParameterCount(), context->realArgumentCount);
     uint argCount = qMin(context->realArgumentCount, context->callData->argc);
     ArrayData::realloc(this, ArrayData::Sparse, 0, argCount, true);
     context->engine->requireArgumentsAccessors(numAccessors);
@@ -189,7 +189,7 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
     if (args->fullyCreated)
         return Object::queryIndexed(m, index);
 
-    uint numAccessors = qMin((int)args->context->function->formalParameterCount, args->context->realArgumentCount);
+    uint numAccessors = qMin((int)args->context->function->formalParameterCount(), args->context->realArgumentCount);
     uint argCount = qMin(args->context->realArgumentCount, args->context->callData->argc);
     if (index >= argCount)
         return PropertyAttributes();
index 8a78b18..4878592 100644 (file)
@@ -55,6 +55,8 @@ DEFINE_MANAGED_VTABLE(ExecutionContext);
 
 CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
 {
+    Q_ASSERT(function->function);
+
     CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
     new (c) CallContext(engine, Type_CallContext);
 
@@ -66,21 +68,20 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData
 
     c->activation = 0;
 
-    if (function->function) {
-        c->compilationUnit = function->function->compilationUnit;
-        c->lookups = c->compilationUnit->runtimeLookups;
-    }
-
+    c->compilationUnit = function->function->compilationUnit;
+    c->lookups = c->compilationUnit->runtimeLookups;
     c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
 
-    if (function->varCount)
-        std::fill(c->locals, c->locals + function->varCount, Primitive::undefinedValue());
+    const CompiledData::Function *compiledFunction = function->function->compiledFunction;
+    int nLocals = compiledFunction->nLocals;
+    if (nLocals)
+        std::fill(c->locals, c->locals + nLocals, Primitive::undefinedValue());
 
-    c->callData = reinterpret_cast<CallData *>(c->locals + function->varCount);
+    c->callData = reinterpret_cast<CallData *>(c->locals + nLocals);
     ::memcpy(c->callData, callData, sizeof(CallData) + (callData->argc - 1) * sizeof(Value));
-    if (callData->argc < static_cast<int>(function->formalParameterCount))
-        std::fill(c->callData->args + c->callData->argc, c->callData->args + function->formalParameterCount, Primitive::undefinedValue());
-    c->callData->argc = qMax((uint)callData->argc, function->formalParameterCount);
+    if (callData->argc < static_cast<int>(compiledFunction->nFormals))
+        std::fill(c->callData->args + c->callData->argc, c->callData->args + compiledFunction->nFormals, Primitive::undefinedValue());
+    c->callData->argc = qMax((uint)callData->argc, compiledFunction->nFormals);
 
     return c;
 }
@@ -145,7 +146,7 @@ unsigned int ExecutionContext::formalCount() const
     if (type < Type_SimpleCallContext)
         return 0;
     QV4::FunctionObject *f = static_cast<const CallContext *>(this)->function;
-    return f ? f->formalParameterCount : 0;
+    return f ? f->formalParameterCount() : 0;
 }
 
 String * const *ExecutionContext::variables() const
@@ -161,7 +162,7 @@ unsigned int ExecutionContext::variableCount() const
     if (type < Type_SimpleCallContext)
         return 0;
     QV4::FunctionObject *f = static_cast<const CallContext *>(this)->function;
-    return f ? f->varCount : 0;
+    return f ? f->varCount() : 0;
 }
 
 
@@ -215,8 +216,8 @@ CallContext::CallContext(ExecutionEngine *engine, ObjectRef qml, FunctionObject
     }
 
     locals = (Value *)(this + 1);
-    if (function->varCount)
-        std::fill(locals, locals + function->varCount, Primitive::undefinedValue());
+    if (function->varCount())
+        std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
 }
 
 
@@ -259,7 +260,7 @@ bool ExecutionContext::deleteProperty(const StringRef name)
 
 bool CallContext::needsOwnArguments() const
 {
-    return function->needsActivation || callData->argc < static_cast<int>(function->formalParameterCount);
+    return function->needsActivation || callData->argc < static_cast<int>(function->formalParameterCount());
 }
 
 void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine)
@@ -314,10 +315,10 @@ void ExecutionContext::setProperty(const StringRef name, const ValueRef value)
                 if (c->function->function) {
                     uint index = c->function->function->internalClass->find(name);
                     if (index < UINT_MAX) {
-                        if (index < c->function->formalParameterCount) {
-                            c->callData->args[c->function->formalParameterCount - index - 1] = *value;
+                        if (index < c->function->formalParameterCount()) {
+                            c->callData->args[c->function->formalParameterCount() - index - 1] = *value;
                         } else {
-                            index -= c->function->formalParameterCount;
+                            index -= c->function->formalParameterCount();
                             c->locals[index] = *value;
                         }
                         return;
@@ -380,9 +381,9 @@ ReturnedValue ExecutionContext::getProperty(const StringRef name)
             if (f->function && (f->needsActivation || hasWith || hasCatchScope)) {
                 uint index = f->function->internalClass->find(name);
                 if (index < UINT_MAX) {
-                    if (index < c->function->formalParameterCount)
-                        return c->callData->args[c->function->formalParameterCount - index - 1].asReturnedValue();
-                    return c->locals[index - c->function->formalParameterCount].asReturnedValue();
+                    if (index < c->function->formalParameterCount())
+                        return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+                    return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
                 }
             }
             if (c->activation) {
@@ -446,9 +447,9 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR
             if (f->function && (f->needsActivation || hasWith || hasCatchScope)) {
                 uint index = f->function->internalClass->find(name);
                 if (index < UINT_MAX) {
-                    if (index < c->function->formalParameterCount)
-                        return c->callData->args[c->function->formalParameterCount - index - 1].asReturnedValue();
-                    return c->locals[index - c->function->formalParameterCount].asReturnedValue();
+                    if (index < c->function->formalParameterCount())
+                        return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+                    return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
                 }
             }
             if (c->activation) {
index c22d983..952582a 100644 (file)
@@ -256,7 +256,7 @@ inline Scope::Scope(ExecutionContext *ctx)
 
 /* Function *f, int argc */
 #define requiredMemoryForExecutionContect(f, argc) \
-    ((sizeof(CallContext) + 7) & ~7) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount)) + sizeof(CallData)
+    ((sizeof(CallContext) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData)
 
 } // namespace QV4
 
index e8a442f..f0002b3 100644 (file)
@@ -77,8 +77,6 @@ DEFINE_OBJECT_VTABLE(FunctionObject);
 FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto)
     : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass)
     , scope(scope)
-    , formalParameterCount(0)
-    , varCount(0)
     , function(0)
     , protoCacheClass(0)
     , protoCacheIndex(UINT_MAX)
@@ -89,8 +87,6 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bo
 FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
     : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass)
     , scope(scope)
-    , formalParameterCount(0)
-    , varCount(0)
     , function(0)
     , protoCacheClass(0)
     , protoCacheIndex(UINT_MAX)
@@ -107,8 +103,6 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, boo
 FunctionObject::FunctionObject(InternalClass *ic)
     : Object(ic)
     , scope(ic->engine->rootContext)
-    , formalParameterCount(0)
-    , varCount(0)
     , function(0)
 {
     name = ic->engine->id_undefined;
@@ -171,11 +165,6 @@ void FunctionObject::markObjects(Managed *that, ExecutionEngine *e)
     FunctionObject *o = static_cast<FunctionObject *>(that);
     if (o->name.managed())
         o->name->mark(e);
-    // these are marked in VM::Function:
-//    for (uint i = 0; i < formalParameterCount; ++i)
-//        formalParameterList[i]->mark();
-//    for (uint i = 0; i < varCount; ++i)
-//        varList[i]->mark();
     o->scope->mark(e);
 
     Object::markObjects(that, e);
@@ -416,10 +405,8 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
 
     needsActivation = function->needsActivation();
     strictMode = function->isStrict();
-    formalParameterCount = function->compiledFunction->nFormals;
-    varCount = function->internalClass->size - function->compiledFunction->nFormals;
 
-    defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount));
+    defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount()));
 
     if (scope->strictMode) {
         Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
@@ -501,10 +488,8 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
 
     needsActivation = function->needsActivation();
     strictMode = function->isStrict();
-    formalParameterCount = function->compiledFunction->nFormals;
-    varCount = function->internalClass->size - function->compiledFunction->nFormals;
 
-    defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount));
+    defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(formalParameterCount()));
 
     if (scope->strictMode) {
         Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
@@ -536,8 +521,8 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
     ctx.compilationUnit = f->function->compilationUnit;
     ctx.lookups = ctx.compilationUnit->runtimeLookups;
     ctx.outer = f->scope;
-    ctx.locals = v4->stackPush(f->varCount);
-    while (callData->argc < (int)f->formalParameterCount) {
+    ctx.locals = v4->stackPush(f->varCount());
+    while (callData->argc < (int)f->formalParameterCount()) {
         callData->args[callData->argc] = Encode::undefined();
         ++callData->argc;
     }
@@ -573,8 +558,8 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
     ctx.compilationUnit = f->function->compilationUnit;
     ctx.lookups = ctx.compilationUnit->runtimeLookups;
     ctx.outer = f->scope;
-    ctx.locals = v4->stackPush(f->varCount);
-    while (callData->argc < (int)f->formalParameterCount) {
+    ctx.locals = v4->stackPush(f->varCount());
+    while (callData->argc < (int)f->formalParameterCount()) {
         callData->args[callData->argc] = Encode::undefined();
         ++callData->argc;
     }
index 1f5bced..ac7fe5d 100644 (file)
@@ -49,6 +49,7 @@
 #include "qv4string_p.h"
 #include "qv4managed_p.h"
 #include "qv4property_p.h"
+#include "qv4function_p.h"
 #include "qv4objectiterator_p.h"
 
 #include <QtCore/QString>
@@ -112,8 +113,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
 
     ExecutionContext *scope;
     StringValue name;
-    unsigned int formalParameterCount;
-    unsigned int varCount;
+    unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
+    unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
     Function *function;
     InternalClass *protoCacheClass;
     uint protoCacheIndex;
index cb5424b..195eac6 100644 (file)
@@ -111,7 +111,7 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
     Q_ASSERT(This->function);
 
     CallContext *ctx = This->qmlContext;
-    std::fill(ctx->locals, ctx->locals + ctx->function->varCount, Primitive::undefinedValue());
+    std::fill(ctx->locals, ctx->locals + ctx->function->varCount(), Primitive::undefinedValue());
     engine->pushContext(ctx);
     ScopedValue result(scope, This->function->code(ctx, This->function->codeData));
     engine->popContext();