From 51e7447481a472ef542e7c6e7b669574ba366a9d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 16 Aug 2013 08:53:47 +0200 Subject: [PATCH] Optimize contruction of Arguments objects Change-Id: If77bff28a25462a6069d646a2594dd903fefb9e5 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4argumentsobject.cpp | 39 +++++++++++++++++++++++--------- src/qml/jsruntime/qv4argumentsobject_p.h | 5 ++++ src/qml/jsruntime/qv4engine.cpp | 5 ++++ src/qml/jsruntime/qv4engine_p.h | 3 +++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 6247ef1..07374a0 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -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) diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 3d760b8..05016cc 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -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); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index acaae46..ddeb20a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -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); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index a6bf2ef..3dbab04 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -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; -- 2.7.4