aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4functionobject.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-09-01 15:16:19 +0200
committerLars Knoll <lars.knoll@qt.io>2017-10-23 06:27:53 +0000
commit2f1e755a623bc834f91204d7414a3588b4f3b5d9 (patch)
tree07222e061f1542ba36de4ce273a43ab70e461b68 /src/qml/jsruntime/qv4functionobject.cpp
parent44a47106419ea4daea077320cf5f857fe6ae8b47 (diff)
Optimize Function.apply and calling bound functions
Change-Id: I11d2db6c912f52ec6dff90a2637644689d8d6fb6 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4functionobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp131
1 files changed, 62 insertions, 69 deletions
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 98b3766242..36c5c4441a 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -45,7 +45,6 @@
#include "qv4arrayobject_p.h"
#include "qv4scopedvalue_p.h"
-#include "qv4jscall_p.h"
#include "qv4argumentsobject_p.h"
#include <private/qqmljsengine_p.h>
@@ -268,50 +267,47 @@ ReturnedValue FunctionPrototype::method_toString(const BuiltinFunction *b, CallD
ReturnedValue FunctionPrototype::method_apply(const BuiltinFunction *b, CallData *callData)
{
ExecutionEngine *v4 = b->engine();
- Scope scope(v4);
- FunctionObject *o = callData->thisObject.as<FunctionObject>();
+ callData->function = callData->thisObject;
+ FunctionObject *o = callData->function.as<FunctionObject>();
if (!o)
return v4->throwTypeError();
-
- ScopedValue arg(scope, callData->argument(1));
-
- ScopedObject arr(scope, arg);
-
- quint32 len;
- if (!arr) {
- len = 0;
- if (!arg->isNullOrUndefined())
- return v4->throwTypeError();
- } else {
- len = arr->getLength();
- }
-
- JSCall jsCall(scope, o, len);
-
- if (len) {
- if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
- QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>();
- int l = qMin(len, (uint)a->d()->context->argc());
- memcpy(jsCall->args, a->d()->context->args(), l*sizeof(Value));
- for (quint32 i = l; i < len; ++i)
- jsCall->args[i] = Primitive::undefinedValue();
- } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
- auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
- uint alen = sad ? sad->values.size : 0;
- if (alen > len)
- alen = len;
- for (uint i = 0; i < alen; ++i)
- jsCall->args[i] = sad->data(i);
- for (quint32 i = alen; i < len; ++i)
- jsCall->args[i] = Primitive::undefinedValue();
- } else {
- for (quint32 i = 0; i < len; ++i)
- jsCall->args[i] = arr->getIndexed(i);
+ callData->thisObject = callData->argument(0);
+ callData->accumulator = callData->argument(1);
+
+ if (callData->accumulator.isObject()) {
+ Object *arr = static_cast<Object *>(&callData->accumulator);
+ uint len = arr->getLength();
+ callData->setArgc(len);
+
+ v4->jsStackTop = callData->args + len;
+ if (len) {
+ if (ArgumentsObject::isNonStrictArgumentsObject(arr) && !arr->cast<ArgumentsObject>()->fullyCreated()) {
+ QV4::ArgumentsObject *a = arr->cast<ArgumentsObject>();
+ int l = qMin(len, (uint)a->d()->context->argc());
+ memcpy(callData->args, a->d()->context->args(), l*sizeof(Value));
+ for (quint32 i = l; i < len; ++i)
+ callData->args[i] = Primitive::undefinedValue();
+ } else if (arr->arrayType() == Heap::ArrayData::Simple && !arr->protoHasArray()) {
+ auto sad = static_cast<Heap::SimpleArrayData *>(arr->arrayData());
+ uint alen = sad ? sad->values.size : 0;
+ if (alen > len)
+ alen = len;
+ for (uint i = 0; i < alen; ++i)
+ callData->args[i] = sad->data(i);
+ for (quint32 i = alen; i < len; ++i)
+ callData->args[i] = Primitive::undefinedValue();
+ } else {
+ for (quint32 i = 0; i < len; ++i)
+ callData->args[i] = arr->getIndexed(i);
+ }
}
+ } else if (!callData->accumulator.isNullOrUndefined()) {
+ return v4->throwTypeError();
+ } else {
+ callData->setArgc(0);
}
- jsCall->thisObject = callData->argument(0);
- return jsCall.call();
+ return o->call(callData);
}
ReturnedValue FunctionPrototype::method_call(const BuiltinFunction *b, CallData *callData)
@@ -478,41 +474,38 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject
f->insertMember(s.engine->id_caller(), pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
-ReturnedValue BoundFunction::call(const Managed *that, CallData *dd)
+ReturnedValue BoundFunction::call(const Managed *that, CallData *callData)
{
const BoundFunction *f = static_cast<const BoundFunction *>(that);
- Scope scope(f->engine());
-
- if (scope.hasException())
- return Encode::undefined();
-
- Scoped<MemberData> boundArgs(scope, f->boundArgs());
- JSCall jsCall(scope, f->target(), (boundArgs ? boundArgs->size() : 0) + dd->argc());
- jsCall->thisObject = f->boundThis();
- Value *argp = jsCall->args;
- if (boundArgs) {
- memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
- argp += boundArgs->size();
+ Heap::MemberData *boundArgs = f->boundArgs();
+
+ int nBoundArgs = boundArgs ? boundArgs->values.size : 0;
+ if (nBoundArgs) {
+ memmove(&callData->args + nBoundArgs, &callData->args, callData->argc()*sizeof(Value));
+ memcpy(callData->args, boundArgs->values.data(), nBoundArgs*sizeof(Value));
+ callData->setArgc(callData->argc() + nBoundArgs);
+ f->engine()->jsStackTop += nBoundArgs;
}
- memcpy(argp, dd->args, dd->argc()*sizeof(Value));
- return jsCall.call();
+
+ callData->thisObject = f->boundThis();
+ callData->function = f->target();
+ return static_cast<FunctionObject &>(callData->function).call(callData);
}
-ReturnedValue BoundFunction::construct(const Managed *that, CallData *dd)
+ReturnedValue BoundFunction::construct(const Managed *that, CallData *callData)
{
const BoundFunction *f = static_cast<const BoundFunction *>(that);
- Scope scope(f->engine());
-
- if (scope.hasException())
- return Encode::undefined();
-
- Scoped<MemberData> boundArgs(scope, f->boundArgs());
- JSCall jsCall(scope, f->target(), (boundArgs ? boundArgs->size() : 0) + dd->argc());
- Value *argp = jsCall->args;
- if (boundArgs) {
- memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
- argp += boundArgs->size();
+ Heap::MemberData *boundArgs = f->boundArgs();
+
+ int nBoundArgs = boundArgs ? boundArgs->values.size : 0;
+ if (nBoundArgs) {
+ memmove(callData->args + nBoundArgs, callData->args, callData->argc()*sizeof(Value));
+ memcpy(callData->args, boundArgs->values.data(), nBoundArgs*sizeof(Value));
+ callData->setArgc(callData->argc() + nBoundArgs);
+ f->engine()->jsStackTop += nBoundArgs;
}
- memcpy(argp, dd->args, dd->argc()*sizeof(Value));
- return jsCall.callAsConstructor();
+
+ callData->thisObject = f->boundThis();
+ callData->function = f->target();
+ return static_cast<FunctionObject &>(callData->function).construct(callData);
}