aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-11-14 11:08:41 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-22 14:54:12 +0100
commitce26bfcb3952dcd1238e7aa07b9ab1d9585c9871 (patch)
treee639703f38ff6b7a9407b7951f815ba9e2f11da8 /src/qml/jsruntime
parent9bf5e87ef0abd3c4612baca66c79e2d33f8fbfb9 (diff)
Speed up arguments object
Don't fully create the arguments object unless required. In the 95% use case, we can avoid creating any array based data structures for the arguments object and directly manipulate the functions arguments. only create the full data structure for the other 5%. Speeds up the raytrace test by 50%, gives around 10% overall on v8-bench. Change-Id: If727d28b96585e83314f544031a6c3ca1817ea19 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp101
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4object.cpp2
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp11
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp7
6 files changed, 110 insertions, 23 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index ed010b1230..4bf4d19576 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -47,10 +47,11 @@ using namespace QV4;
DEFINE_MANAGED_VTABLE(ArgumentsObject);
ArgumentsObject::ArgumentsObject(CallContext *context)
- : Object(context->engine), context(context)
+ : Object(context->engine), context(context), fullyCreated(false)
{
vtbl = &static_vtbl;
type = Type_ArgumentsObject;
+ flags &= ~SimpleArray;
ExecutionEngine *v4 = context->engine;
Scope scope(v4);
@@ -60,8 +61,8 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
internalClass = v4->strictArgumentsObjectClass;
Property pd = Property::fromAccessor(v4->thrower, v4->thrower);
- assert(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
- assert(CallerPropertyIndex == internalClass->find(context->engine->id_caller));
+ Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
+ Q_ASSERT(CallerPropertyIndex == internalClass->find(context->engine->id_caller));
memberData[CalleePropertyIndex] = pd;
memberData[CallerPropertyIndex] = pd;
@@ -69,27 +70,12 @@ ArgumentsObject::ArgumentsObject(CallContext *context)
for (int i = 0; i < context->callData->argc; ++i)
arrayData[i].value = context->callData->args[i];
arrayDataLen = context->callData->argc;
+ fullyCreated = true;
} else {
internalClass = engine()->argumentsObjectClass;
Q_ASSERT(CalleePropertyIndex == internalClass->find(context->engine->id_callee));
memberData[CalleePropertyIndex].value = context->function->asReturnedValue();
isNonStrictArgumentsObject = true;
-
- uint numAccessors = qMin((int)context->function->formalParameterCount, context->realArgumentCount);
- uint argCount = qMin(context->realArgumentCount, context->callData->argc);
- arrayReserve(argCount);
- ensureArrayAttributes();
- context->engine->requireArgumentsAccessors(numAccessors);
- for (uint i = 0; i < (uint)numAccessors; ++i) {
- mappedArguments.append(context->callData->args[i]);
- arrayData[i] = context->engine->argumentsAccessors.at(i);
- arrayAttributes[i] = Attr_Accessor;
- }
- for (uint i = numAccessors; i < argCount; ++i) {
- arrayData[i] = Property::fromValue(context->callData->args[i]);
- arrayAttributes[i] = Attr_Data;
- }
- arrayDataLen = argCount;
}
Q_ASSERT(LengthPropertyIndex == internalClass->find(context->engine->id_length));
Property *lp = memberData + ArrayObject::LengthPropertyIndex;
@@ -101,8 +87,34 @@ void ArgumentsObject::destroy(Managed *that)
static_cast<ArgumentsObject *>(that)->~ArgumentsObject();
}
+void ArgumentsObject::fullyCreate()
+{
+ if (fullyCreated)
+ return;
+
+ uint numAccessors = qMin((int)context->function->formalParameterCount, context->realArgumentCount);
+ uint argCount = qMin(context->realArgumentCount, context->callData->argc);
+ arrayReserve(argCount);
+ ensureArrayAttributes();
+ context->engine->requireArgumentsAccessors(numAccessors);
+ for (uint i = 0; i < (uint)numAccessors; ++i) {
+ mappedArguments.append(context->callData->args[i]);
+ arrayData[i] = context->engine->argumentsAccessors.at(i);
+ arrayAttributes[i] = Attr_Accessor;
+ }
+ for (uint i = numAccessors; i < argCount; ++i) {
+ arrayData[i] = Property::fromValue(context->callData->args[i]);
+ arrayAttributes[i] = Attr_Data;
+ }
+ arrayDataLen = argCount;
+
+ fullyCreated = true;
+}
+
bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs)
{
+ fullyCreate();
+
Scope scope(ctx);
uint pidx = propertyIndexFromArrayIndex(index);
Property *pd = arrayData + pidx;
@@ -143,6 +155,57 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
return result;
}
+ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasProperty)
+{
+ ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ if (args->fullyCreated)
+ return Object::getIndexed(m, index, hasProperty);
+
+ if (index < static_cast<uint>(args->context->callData->argc)) {
+ if (hasProperty)
+ *hasProperty = true;
+ return args->context->callData->args[index].asReturnedValue();
+ }
+ return Encode::undefined();
+}
+
+void ArgumentsObject::putIndexed(Managed *m, uint index, const ValueRef value)
+{
+ ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ if (!args->fullyCreated && index >= static_cast<uint>(args->context->callData->argc))
+ args->fullyCreate();
+
+ if (args->fullyCreated) {
+ Object::putIndexed(m, index, value);
+ return;
+ }
+
+ args->context->callData->args[index] = value;
+}
+
+bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
+{
+ ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
+ if (!args->fullyCreated)
+ args->fullyCreate();
+ return Object::deleteIndexedProperty(m, index);
+}
+
+PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
+{
+ const ArgumentsObject *args = static_cast<const ArgumentsObject *>(m);
+ if (args->fullyCreated)
+ return Object::queryIndexed(m, index);
+
+ 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();
+ if (index >= numAccessors)
+ return Attr_Data;
+ return Attr_Accessor;
+}
+
DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction);
ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 7a5b0817a3..7c58c48bcc 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -74,20 +74,26 @@ struct ArgumentsSetterFunction: FunctionObject
struct ArgumentsObject: Object {
Q_MANAGED
CallContext *context;
+ bool fullyCreated;
QVector<SafeValue> mappedArguments;
ArgumentsObject(CallContext *context);
~ArgumentsObject() {}
+
enum {
LengthPropertyIndex = 0,
CalleePropertyIndex = 1,
CallerPropertyIndex = 2
};
bool defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs);
-
+ static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static void putIndexed(Managed *m, uint index, const ValueRef value);
+ static bool deleteIndexedProperty(Managed *m, uint index);
+ static PropertyAttributes queryIndexed(const Managed *m, uint index);
static void markObjects(Managed *that, ExecutionEngine *e);
-protected:
static void destroy(Managed *);
+
+ void fullyCreate();
};
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index aa1cb89a44..8c3131c565 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -348,7 +348,7 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
ScopedCallData callData(scope, len);
if (len) {
- if (arr->protoHasArray() || arr->hasAccessorProperty) {
+ if (!(arr->flags & SimpleArray) || arr->protoHasArray() || arr->hasAccessorProperty) {
for (quint32 i = 0; i < len; ++i)
callData->args[i] = arr->getIndexed(i);
} else {
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index cca7d2b26a..e4df95716d 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -1133,7 +1133,7 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
Scope scope(engine());
ScopedValue value(scope);
- if (!(flags & SimpleArray) || o->protoHasArray() || o->arrayAttributes) {
+ if (!(o->flags & SimpleArray) || o->protoHasArray()) {
// lets be safe and slow
for (uint i = fromIndex; i < endIndex; ++i) {
bool exists;
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 62595b5176..04fa504991 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -42,6 +42,7 @@
#include "qv4object_p.h"
#include "qv4stringobject_p.h"
#include "qv4identifier_p.h"
+#include "qv4argumentsobject_p.h"
using namespace QV4;
@@ -56,6 +57,11 @@ ObjectIterator::ObjectIterator(SafeObject *scratch1, SafeObject *scratch2, const
object = o;
current = o;
tmpDynamicProperty.value = Primitive::undefinedValue();
+
+ if (object && object->isNonStrictArgumentsObject) {
+ Scope scope(object->engine());
+ Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
+ }
}
ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
@@ -69,6 +75,11 @@ ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
object = o;
current = o;
tmpDynamicProperty.value = Primitive::undefinedValue();
+
+ if (object && object->isNonStrictArgumentsObject) {
+ Scope scope(object->engine());
+ Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
+ }
}
Property *ObjectIterator::next(StringRef name, uint *index, PropertyAttributes *attrs)
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 4369267278..f17bd7d5ba 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -41,6 +41,7 @@
#include "qv4objectproto_p.h"
+#include "qv4argumentsobject_p.h"
#include "qv4mm_p.h"
#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
@@ -156,6 +157,9 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
if (!O)
return ctx->throwTypeError();
+ if (O->isNonStrictArgumentsObject)
+ Scoped<ArgumentsObject>(scope, O)->fullyCreate();
+
ScopedValue v(scope, ctx->argument(1));
Scoped<String> name(scope, v->toString(ctx));
if (scope.hasException())
@@ -283,6 +287,9 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
if (!o)
return ctx->throwTypeError();
+ if (o->isNonStrictArgumentsObject)
+ Scoped<ArgumentsObject>(scope, o)->fullyCreate();
+
o->extensible = false;
o->internalClass = o->internalClass->frozen();