Optimize contruction of Arguments objects
authorLars Knoll <lars.knoll@digia.com>
Fri, 16 Aug 2013 06:53:47 +0000 (08:53 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 17 Aug 2013 07:26:24 +0000 (09:26 +0200)
Change-Id: If77bff28a25462a6069d646a2594dd903fefb9e5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/jsruntime/qv4argumentsobject.cpp
src/qml/jsruntime/qv4argumentsobject_p.h
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h

index 6247ef1..07374a0 100644 (file)
@@ -56,28 +56,45 @@ ArgumentsObject::ArgumentsObject(CallContext *context, int formalParameterCount,
     vtbl = &static_vtbl;
     type = Type_ArgumentsObject;
 
-    defineDefaultProperty(context->engine->id_length, Value::fromInt32(actualParameterCount));
     if (context->strictMode) {
-        for (uint i = 0; i < context->argumentCount; ++i)
-            Object::put(context, QString::number(i), context->arguments[i]);
+        internalClass = engine()->strictArgumentsObjectClass;
+
         FunctionObject *thrower = context->engine->newBuiltinFunction(context, 0, throwTypeError);
         Property pd = Property::fromAccessor(thrower, thrower);
-        __defineOwnProperty__(context, QStringLiteral("callee"), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
-        __defineOwnProperty__(context, QStringLiteral("caller"), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+        assert(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
+        assert(CallerPropertyIndex == internalClass->find(context->engine->id_caller));
+        memberData[CalleePropertyIndex] = pd;
+        memberData[CallerPropertyIndex] = pd;
+
+        arrayReserve(context->argumentCount);
+        for (unsigned int i = 0; i < context->argumentCount; ++i)
+            arrayData[i].value = context->arguments[i];
+        arrayDataLen = context->argumentCount;
     } else {
+        internalClass = engine()->argumentsObjectClass;
+        assert(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
+        memberData[CalleePropertyIndex].value = Value::fromObject(context->function);
+        isNonStrictArgumentsObject = true;
+
         uint numAccessors = qMin(formalParameterCount, actualParameterCount);
+        uint argCount = qMin((uint)actualParameterCount, context->argumentCount);
+        arrayReserve(argCount);
+        ensureArrayAttributes();
         context->engine->requireArgumentsAccessors(numAccessors);
         for (uint i = 0; i < (uint)numAccessors; ++i) {
             mappedArguments.append(context->argument(i));
-            __defineOwnProperty__(context, i, context->engine->argumentsAccessors.at(i), Attr_Accessor);
+            arrayData[i] = context->engine->argumentsAccessors.at(i);
+            arrayAttributes[i] = Attr_Accessor;
         }
-        for (uint i = numAccessors; i < qMin((uint)actualParameterCount, context->argumentCount); ++i) {
-            Property pd = Property::fromValue(context->argument(i));
-            __defineOwnProperty__(context, i, pd, Attr_Data);
+        for (uint i = numAccessors; i < argCount; ++i) {
+            arrayData[i] = Property::fromValue(context->argument(i));
+            arrayAttributes[i] = Attr_Data;
         }
-        defineDefaultProperty(context, QStringLiteral("callee"), Value::fromObject(context->function));
-        isNonStrictArgumentsObject = true;
+        arrayDataLen = argCount;
     }
+    assert(LengthPropertyIndex == internalClass->find(context->engine->id_length));
+    Property *lp = memberData + ArrayObject::LengthPropertyIndex;
+    lp->value = Value::fromInt32(actualParameterCount);
 }
 
 void ArgumentsObject::destroy(Managed *that)
index 3d760b8..05016cc 100644 (file)
@@ -81,6 +81,11 @@ struct ArgumentsObject: Object {
     ArgumentsObject(CallContext *context, int formalParameterCount, int actualParameterCount);
     ~ArgumentsObject() {}
 
+    enum {
+        LengthPropertyIndex = 0,
+        CalleePropertyIndex = 1,
+        CallerPropertyIndex = 2
+    };
     bool defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs);
 
     static void markObjects(Managed *that);
index acaae46..ddeb20a 100644 (file)
@@ -124,6 +124,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     id_constructor = newIdentifier(QStringLiteral("constructor"));
     id_arguments = newIdentifier(QStringLiteral("arguments"));
     id_caller = newIdentifier(QStringLiteral("caller"));
+    id_callee = newIdentifier(QStringLiteral("callee"));
     id_this = newIdentifier(QStringLiteral("this"));
     id___proto__ = newIdentifier(QStringLiteral("__proto__"));
     id_enumerable = newIdentifier(QStringLiteral("enumerable"));
@@ -137,6 +138,10 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
     id_name = newIdentifier(QStringLiteral("name"));
 
     arrayClass = emptyClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
+    InternalClass *argsClass = emptyClass->addMember(id_length, Attr_NotEnumerable);
+    argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
+    strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
+    strictArgumentsObjectClass = strictArgumentsObjectClass->addMember(id_caller, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
     initRootContext();
 
     objectPrototype = new (memoryManager) ObjectPrototype(this);
index a6bf2ef..3dbab04 100644 (file)
@@ -167,6 +167,8 @@ struct Q_QML_EXPORT ExecutionEngine
     QQmlJS::MemoryPool classPool;
     InternalClass *emptyClass;
     InternalClass *arrayClass;
+    InternalClass *argumentsObjectClass;
+    InternalClass *strictArgumentsObjectClass;
 
     EvalFunction *evalFunction;
 
@@ -186,6 +188,7 @@ struct Q_QML_EXPORT ExecutionEngine
     String *id_constructor;
     String *id_arguments;
     String *id_caller;
+    String *id_callee;
     String *id_this;
     String *id___proto__;
     String *id_enumerable;