aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-10-20 17:19:25 +0200
committerLars Knoll <lars.knoll@qt.io>2017-11-07 09:00:48 +0000
commite72306a6f2aeb2bddbb462c205db8fad2fb5a1a4 (patch)
tree3b83e1cead58d97c2b055283487500472ca7d698 /src
parentbc5ff76e5afe6356bebb344c9a5d8b304e852f3c (diff)
Further cleanup JSCallData
Avoid allocations on the JS stack if possible Change-Id: I344cd6dceb6264314f9d22c94db22b22d1d24d14 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsapi/qjsvalue.cpp4
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp16
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4include.cpp2
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h41
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp4
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp10
-rw-r--r--src/qml/jsruntime/qv4object.cpp8
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp100
-rw-r--r--src/qml/jsruntime/qv4script.cpp11
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/types/qquickworkerscript.cpp6
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp2
21 files changed, 113 insertions, 123 deletions
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 654a497950..1c634467fc 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -658,7 +658,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
Scope scope(engine);
JSCallData jsCallData(scope, args.length());
- jsCallData->thisObject = engine->globalObject;
+ *jsCallData->thisObject = engine->globalObject;
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
@@ -714,7 +714,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
}
JSCallData jsCallData(scope, args.size());
- jsCallData->thisObject = QJSValuePrivate::convertedToValue(engine, instance);
+ *jsCallData->thisObject = QJSValuePrivate::convertedToValue(engine, instance);
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index db0a7db068..b7ac9616b1 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -140,7 +140,7 @@ bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, con
Q_ASSERT(arrayData());
ScopedFunctionObject setter(scope, map->setter());
JSCallData jsCallData(scope, 1);
- jsCallData->thisObject = this->asReturnedValue();
+ *jsCallData->thisObject = this->asReturnedValue();
jsCallData->args[0] = desc->value;
setter->call(jsCallData);
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index eef9ac0820..206e3a9fc3 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -199,7 +199,7 @@ ReturnedValue ArrayPrototype::method_find(const BuiltinFunction *b, CallData *ca
THROW_TYPE_ERROR();
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
ScopedValue v(scope);
ScopedValue result(scope);
@@ -235,7 +235,7 @@ ReturnedValue ArrayPrototype::method_findIndex(const BuiltinFunction *b, CallDat
THROW_TYPE_ERROR();
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
ScopedValue v(scope);
ScopedValue result(scope);
@@ -794,7 +794,7 @@ ReturnedValue ArrayPrototype::method_every(const BuiltinFunction *b, CallData *c
ScopedValue r(scope);
ScopedValue v(scope);
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
bool ok = true;
for (uint k = 0; ok && k < len; ++k) {
@@ -828,7 +828,7 @@ ReturnedValue ArrayPrototype::method_some(const BuiltinFunction *b, CallData *ca
ScopedValue v(scope);
ScopedValue result(scope);
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
for (uint k = 0; k < len; ++k) {
bool exists;
@@ -861,7 +861,7 @@ ReturnedValue ArrayPrototype::method_forEach(const BuiltinFunction *b, CallData
ScopedValue v(scope);
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
for (uint k = 0; k < len; ++k) {
bool exists;
@@ -897,7 +897,7 @@ ReturnedValue ArrayPrototype::method_map(const BuiltinFunction *b, CallData *cal
ScopedValue v(scope);
ScopedValue mapped(scope);
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
for (uint k = 0; k < len; ++k) {
bool exists;
@@ -933,7 +933,7 @@ ReturnedValue ArrayPrototype::method_filter(const BuiltinFunction *b, CallData *
ScopedValue selected(scope);
ScopedValue v(scope);
JSCallData jsCallData(scope, 3);
- jsCallData->thisObject = callData->argument(1);
+ *jsCallData->thisObject = callData->argument(1);
uint to = 0;
for (uint k = 0; k < len; ++k) {
@@ -1039,7 +1039,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const BuiltinFunction *b, CallD
}
JSCallData jsCallData(scope, 4);
- jsCallData->thisObject = Primitive::undefinedValue();
+ *jsCallData->thisObject = Primitive::undefinedValue();
while (k > 0) {
bool kPresent;
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 3397e5418b..71327ea806 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -1452,7 +1452,7 @@ ReturnedValue DatePrototype::method_toJSON(const BuiltinFunction *b, CallData *c
return v4->throwTypeError();
JSCallData jsCallData(scope);
- jsCallData->thisObject = callData->thisObject;
+ *jsCallData->thisObject = callData->thisObject;
return toIso->call(jsCallData);
}
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 4e96b01185..f962aa29bc 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -376,9 +376,9 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function));
JSCallData jsCallData(scope, 0);
if (directCall)
- jsCallData->thisObject = scope.engine->currentStackFrame->thisObject();
+ *jsCallData->thisObject = scope.engine->currentStackFrame->thisObject();
else
- jsCallData->thisObject = scope.engine->globalObject;
+ *jsCallData->thisObject = scope.engine->globalObject;
return e->call(jsCallData);
}
@@ -387,10 +387,12 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
// set the correct v4 function for the context
ctx->d()->v4Function = function;
- JSCallData jsCall(scope);
- jsCall->thisObject = scope.engine->currentStackFrame->thisObject();
- jsCall->context = *ctx;
- return function->call(jsCall.callData());
+ JSCallData jsCallData(scope);
+ *jsCallData->thisObject = scope.engine->currentStackFrame->thisObject();
+ CallData *cData = jsCallData.callData();
+ cData->context = *ctx;
+
+ return function->call(cData);
}
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index df20b2802d..3e04ed63df 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -120,7 +120,7 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
return;
QV4::JSCallData jsCallData(scope, 1);
- jsCallData->thisObject = v4->globalObject->asReturnedValue();
+ *jsCallData->thisObject = v4->globalObject->asReturnedValue();
jsCallData->args[0] = status;
f->call(jsCallData);
if (scope.hasException())
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index 0f22aa1aa7..6d641bf9c5 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -62,42 +62,53 @@ namespace QV4 {
struct JSCallData {
JSCallData(const Scope &scope, int argc = 0, const Value *argv = 0, const Value *thisObject = 0)
+ : scope(scope), argc(argc)
{
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
- ptr = reinterpret_cast<CallData *>(scope.engine->jsStackTop);
- scope.engine->jsStackTop += size;
- ptr->function = Encode::undefined();
- ptr->context = Encode::undefined();
- ptr->accumulator = Encode::undefined();
- ptr->thisObject = thisObject ? thisObject->asReturnedValue() : Encode::undefined();
- ptr->setArgc(argc);
+ if (thisObject)
+ this->thisObject = const_cast<Value *>(thisObject);
+ else
+ this->thisObject = scope.alloc(1);
if (argv)
- memcpy(ptr->args, argv, argc*sizeof(Value));
+ this->args = const_cast<Value *>(argv);
+ else
+ this->args = scope.alloc(argc);
}
- CallData *operator->() const {
- return ptr;
+ JSCallData *operator->() {
+ return this;
}
CallData *callData(const FunctionObject *f = nullptr) const {
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
+ CallData *ptr = reinterpret_cast<CallData *>(scope.engine->jsStackTop);
+ scope.engine->jsStackTop += size;
+ ptr->function = Encode::undefined();
+ ptr->context = Encode::undefined();
+ ptr->accumulator = Encode::undefined();
+ ptr->thisObject = thisObject->asReturnedValue();
+ ptr->setArgc(argc);
+ if (argc)
+ memcpy(ptr->args, args, argc*sizeof(Value));
if (f)
ptr->function = f->asReturnedValue();
return ptr;
}
-
- CallData *ptr;
+ const Scope &scope;
+ int argc;
+ Value *args;
+ Value *thisObject;
};
inline
ReturnedValue FunctionObject::callAsConstructor(const JSCallData &data) const
{
- return d()->jsConstruct(this, data->args, data->argc());
+ return d()->jsConstruct(this, data.args, data.argc);
}
inline
ReturnedValue FunctionObject::call(const JSCallData &data) const
{
- return d()->jsCall(this, &data->thisObject, data->args, data->argc());
+ return d()->jsCall(this, data.thisObject, data.args, data.argc);
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 16018722cb..5e580b8b4d 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -698,7 +698,7 @@ QString Stringify::Str(const QString &key, const Value &v)
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
JSCallData jsCallData(scope, 1);
- jsCallData->thisObject = value;
+ *jsCallData->thisObject = value;
jsCallData->args[0] = v4->newString(key);
value = toJSON->call(jsCallData);
}
@@ -710,7 +710,7 @@ QString Stringify::Str(const QString &key, const Value &v)
JSCallData jsCallData(scope, 2);
jsCallData->args[0] = v4->newString(key);
jsCallData->args[1] = value;
- jsCallData->thisObject = holder;
+ *jsCallData->thisObject = holder;
value = replacerFunction->call(jsCallData);
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 87c396be73..ec3482c1e9 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -401,7 +401,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const
return Encode::undefined();
JSCallData jsCallData(scope);
- jsCallData->thisObject = object;
+ *jsCallData->thisObject = object;
return getter->call(jsCallData);
}
}
@@ -423,7 +423,7 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const
return Encode::undefined();
JSCallData jsCallData(scope);
- jsCallData->thisObject = object;
+ *jsCallData->thisObject = object;
return getter->call(jsCallData);
}
}
@@ -448,7 +448,7 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const
return Encode::undefined();
JSCallData jsCallData(scope);
- jsCallData->thisObject = object;
+ *jsCallData->thisObject = object;
return getter->call(jsCallData);
}
}
@@ -503,7 +503,7 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engin
return Encode::undefined();
JSCallData jsCallData(scope);
- jsCallData->thisObject = object;
+ *jsCallData->thisObject = object;
return getter->call(jsCallData);
}
}
@@ -523,7 +523,7 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engin
return Encode::undefined();
JSCallData jsCallData(scope);
- jsCallData->thisObject = object;
+ *jsCallData->thisObject = object;
return getter->call(jsCallData);
}
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 18a831a4ba..357efcc47d 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -108,7 +108,7 @@ ReturnedValue Object::getValue(const Value &thisObject, const Value &v, Property
Scope scope(f->engine());
JSCallData jsCallData(scope);
- jsCallData->thisObject = thisObject;
+ *jsCallData->thisObject = thisObject;
return f->call(jsCallData);
}
@@ -127,7 +127,7 @@ bool Object::putValue(uint memberIndex, const Value &value)
ScopedFunctionObject setter(scope, set);
JSCallData jsCallData(scope, 1);
jsCallData->args[0] = value;
- jsCallData->thisObject = this;
+ *jsCallData->thisObject = this;
setter->call(jsCallData);
return !ic->engine->hasException;
}
@@ -766,7 +766,7 @@ bool Object::internalPut(String *name, const Value &value)
ScopedFunctionObject setter(scope, *memberIndex);
JSCallData jsCallData(scope, 1);
jsCallData->args[0] = value;
- jsCallData->thisObject = this;
+ *jsCallData->thisObject = this;
setter->call(jsCallData);
return !engine->hasException;
}
@@ -831,7 +831,7 @@ bool Object::internalPutIndexed(uint index, const Value &value)
ScopedFunctionObject setter(scope, *arrayIndex);
JSCallData jsCallData(scope, 1);
jsCallData->args[0] = value;
- jsCallData->thisObject = this;
+ *jsCallData->thisObject = this;
setter->call(jsCallData);
return !engine->hasException;
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index c174cb4dcd..9f1ba59b36 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -480,7 +480,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(const BuiltinFunction *b, C
if (!f)
THROW_TYPE_ERROR();
JSCallData jsCallData(scope);
- jsCallData->thisObject = o;
+ *jsCallData->thisObject = o;
return f->call(jsCallData);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index febcc22fa3..074866608c 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -817,7 +817,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::JSCallData jsCallData(scope, argCount);
- jsCallData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
+ *jsCallData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 00882d699c..42981949c9 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -429,12 +429,8 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH
ScopedValue result(scope);
ScopedValue conv(scope, object->get(meth1));
- JSCallData jsCallData(scope, 0);
- jsCallData->thisObject = *object;
-
if (FunctionObject *o = conv->as<FunctionObject>()) {
- jsCallData->function = o;
- result = o->call(jsCallData);
+ result = o->call(object, nullptr, 0);
if (result->isPrimitive())
return result->asReturnedValue();
}
@@ -444,8 +440,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH
conv = object->get(meth2);
if (FunctionObject *o = conv->as<FunctionObject>()) {
- jsCallData->function = o;
- result = o->call(jsCallData);
+ result = o->call(object, nullptr, 0);
if (result->isPrimitive())
return result->asReturnedValue();
}
@@ -983,135 +978,116 @@ ReturnedValue Runtime::method_callPossiblyDirectEval(ExecutionEngine *engine, Va
{
Scope scope(engine);
JSCallData callData(scope, argc, argv);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context);
- callData->function = ctx.getPropertyAndBase(engine->id_eval(), &callData->thisObject);
+ ScopedFunctionObject function(scope, ctx.getPropertyAndBase(engine->id_eval(), callData->thisObject));
if (engine->hasException)
return Encode::undefined();
- if (!callData->function.isFunctionObject()) {
+ if (!function) {
QString objectAsString = QStringLiteral("[null]");
- if (!callData->thisObject.isUndefined())
- objectAsString = callData->thisObject.toQStringNoThrow();
+ if (!callData->thisObject->isUndefined())
+ objectAsString = callData->thisObject->toQStringNoThrow();
QString msg = QStringLiteral("Property 'eval' of object %2 is not a function").arg(objectAsString);
return engine->throwTypeError(msg);
}
- FunctionObject &f = static_cast<FunctionObject &>(callData->function);
-
- if (f.d() == engine->evalFunction()->d())
- return static_cast<EvalFunction &>(f).evalCall(callData.callData(&f), true);
+ if (function->d() == engine->evalFunction()->d())
+ return static_cast<EvalFunction *>(function.getPointer())->evalCall(callData.callData(function), true);
- return f.call(&callData->thisObject, callData->args, callData->argc());
+ return function->call(callData);
}
ReturnedValue Runtime::method_callName(ExecutionEngine *engine, int nameIndex, Value *argv, int argc)
{
Scope scope(engine);
- JSCallData callData(scope, argc, argv);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
-
- callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex];
+ ScopedValue thisObject(scope);
+ ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ExecutionContext &ctx = static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context);
- callData->function = ctx.getPropertyAndBase(static_cast<String *>(&callData->function), &callData->thisObject);
+ ScopedFunctionObject f(scope, ctx.getPropertyAndBase(name, thisObject));
if (engine->hasException)
return Encode::undefined();
- if (!callData->function.isFunctionObject()) {
+ if (!f) {
QString objectAsString = QStringLiteral("[null]");
- if (!callData->thisObject.isUndefined())
- objectAsString = callData->thisObject.toQStringNoThrow();
+ if (!thisObject->isUndefined())
+ objectAsString = thisObject->toQStringNoThrow();
QString msg = QStringLiteral("Property '%1' of object %2 is not a function")
.arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
objectAsString);
return engine->throwTypeError(msg);
}
- FunctionObject &f = static_cast<FunctionObject &>(callData->function);
- return f.call(&callData->thisObject, callData->args, callData->argc());
+ return f->call(thisObject, argv, argc);
}
ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, Value *base, int nameIndex, Value *argv, int argc)
{
Scope scope(engine);
- JSCallData callData(scope, argc, argv, base);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
- if (!callData->thisObject.isObject()) {
- Q_ASSERT(!callData->thisObject.isEmpty());
- if (callData->thisObject.isNullOrUndefined()) {
+ if (!base->isObject()) {
+ Q_ASSERT(!base->isEmpty());
+ if (base->isNullOrUndefined()) {
QString message = QStringLiteral("Cannot call method '%1' of %2")
.arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
- callData->thisObject.toQStringNoThrow());
+ base->toQStringNoThrow());
return engine->throwTypeError(message);
}
- callData->thisObject = RuntimeHelpers::convertToObject(engine, callData->thisObject);
+ ScopedValue thisObject(scope, RuntimeHelpers::convertToObject(engine, *base));
if (engine->hasException) // type error
return Encode::undefined();
+ base = thisObject;
}
- callData->function = engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex];
- callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function));
+ ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(name));
- if (!callData->function.isFunctionObject()) {
+ if (!f) {
QString error = QStringLiteral("Property '%1' of object %2 is not a function")
.arg(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]->toQString(),
- callData->thisObject.toQStringNoThrow());
+ base->toQStringNoThrow());
return engine->throwTypeError(error);
}
- FunctionObject &f = static_cast<FunctionObject &>(callData->function);
- return f.call(&callData->thisObject, callData->args, callData->argc());
+ return f->call(base, argv, argc);
}
ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)
{
- Scope scope(engine);
- JSCallData callData(scope, argc, argv, base);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
-
- Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc());
Lookup *l = engine->currentStackFrame->v4Function->compilationUnit->runtimeLookups + index;
- callData->function = l->getter(l, engine, callData->thisObject);
+ // ok to have the value on the stack here
+ Value f = Value::fromReturnedValue(l->getter(l, engine, *base));
- if (!callData->function.isFunctionObject())
+ if (!f.isFunctionObject())
return engine->throwTypeError();
- FunctionObject &f = static_cast<FunctionObject &>(callData->function);
- return f.call(&callData->thisObject, callData->args, callData->argc());
+ return static_cast<FunctionObject &>(f).call(base, argv, argc);
}
ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)
{
Scope scope(engine);
- JSCallData callData(scope, argc, argv, base);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
+ ScopedValue thisObject(scope, base->toObject(engine));
+ base = thisObject;
- callData->thisObject = callData->thisObject.toObject(engine);
- callData->function = index.toString(engine);
+ ScopedString str(scope, index.toString(engine));
if (engine->hasException)
return Encode::undefined();
- callData->function = static_cast<Object &>(callData->thisObject).get(static_cast<String *>(&callData->function));
- if (!callData->function.isFunctionObject())
+ ScopedFunctionObject f(scope, static_cast<Object *>(base)->get(str));
+ if (!f)
return engine->throwTypeError();
- return static_cast<FunctionObject &>(callData->function).call(&callData->thisObject, callData->args, callData->argc());
+ return f->call(base, argv, argc);
}
ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, Value *argv, int argc)
{
if (!func.isFunctionObject())
return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow()));
-
- Scope scope(engine);
- JSCallData callData(scope, argc, argv);
- Q_ASSERT(callData->args + callData->argc() == engine->jsStackTop);
-
- return static_cast<const FunctionObject &>(func).call(&callData->thisObject, callData->args, callData->argc());
+ return static_cast<const FunctionObject &>(func).call(nullptr, argv, argc);
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 8ca4985b32..c3b19ac77c 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -154,14 +154,15 @@ ReturnedValue Script::run()
QV4::JSCallData jsCall(valueScope);
jsCall->thisObject = engine->globalObject;
- jsCall->context = *context;
- return vmFunction->call(jsCall.callData());
+ QV4::CallData *cData = jsCall.callData();
+ cData->context = *context;
+ return vmFunction->call(cData);
} else {
Scoped<QmlContext> qml(valueScope, qmlContext.value());
JSCallData jsCall(valueScope);
- jsCall->thisObject = Primitive::undefinedValue();
- jsCall->context = *qml;
- return vmFunction->call(jsCall.callData());
+ QV4::CallData *cData = jsCall.callData();
+ cData->context = *qml;
+ return vmFunction->call(cData);
}
}
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 4dd71fe582..78cd7529d8 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -423,7 +423,7 @@ public:
JSCallData jsCallData(scope, 2);
jsCallData->args[0] = convertElementToValue(m_v4, lhs);
jsCallData->args[1] = convertElementToValue(m_v4, rhs);
- jsCallData->thisObject = m_v4->globalObject;
+ *jsCallData->thisObject = m_v4->globalObject;
QV4::ScopedValue result(scope, compare->call(jsCallData));
return result->toNumber() < 0;
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index d8bd51ac39..7e5b306ebe 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -584,7 +584,7 @@ ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData
result.reserve(string.length() + 10*numStringMatches);
ScopedValue entry(scope);
JSCallData jsCallData(scope, numCaptures + 2);
- jsCallData->thisObject = Primitive::undefinedValue();
+ *jsCallData->thisObject = Primitive::undefinedValue();
int lastEnd = 0;
for (int i = 0; i < numStringMatches; ++i) {
for (int k = 0; k < numCaptures; ++k) {
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 956083238b..c0e4d2f066 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1548,7 +1548,7 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QV4::ScopedFunctionObject f(scope, d()->statusChanged);
if (f) {
QV4::JSCallData jsCallData(scope, 1);
- jsCallData->thisObject = this;
+ *jsCallData->thisObject = this;
jsCallData->args[0] = QV4::Primitive::fromUInt32(s);
f->call(jsCallData);
if (scope.hasException()) {
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 8b01630628..df4030e522 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -68,7 +68,7 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en
Q_ASSERT(callback);
const int argCount = array ? array->getLength() : 0;
QV4::JSCallData jsCallData(scope, argCount);
- jsCallData->thisObject = QV4::Encode::undefined();
+ *jsCallData->thisObject = QV4::Encode::undefined();
for (int i = 0; i < argCount; i++) {
jsCallData->args[i] = array->getIndexed(i);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 8b5db2f9f1..281d64ac79 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -951,7 +951,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
const unsigned int parameterCount = function->formalParameterCount();
QV4::JSCallData jsCallData(scope, parameterCount);
- jsCallData->thisObject = ep->v8engine()->global();
+ *jsCallData->thisObject = ep->v8engine()->global();
for (uint ii = 0; ii < parameterCount; ++ii)
jsCallData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 6db1372465..346f2e6a61 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -250,7 +250,7 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QQuickWorkerScriptEnginePrivate::method_sendMessage));
QV4::JSCallData jsCallData(scope, 1);
jsCallData->args[0] = function;
- jsCallData->thisObject = global();
+ *jsCallData->thisObject = global();
createsend.set(scope.engine, createsendconstructor->call(jsCallData));
}
@@ -267,7 +267,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
QV4::ScopedValue v(scope);
QV4::JSCallData jsCallData(scope, 1);
jsCallData->args[0] = QV4::Primitive::fromInt32(id);
- jsCallData->thisObject = global();
+ *jsCallData->thisObject = global();
v = f->call(jsCallData);
if (scope.hasException())
v = scope.engine->catchException();
@@ -367,7 +367,7 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
Q_ASSERT(!!qmlContext);
QV4::JSCallData jsCallData(scope, 2);
- jsCallData->thisObject = workerEngine->global();
+ *jsCallData->thisObject = workerEngine->global();
jsCallData->args[0] = qmlContext->d()->qml(); // ###
jsCallData->args[1] = value;
f->call(jsCallData);
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index f9b5a7af81..57936d8cec 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -731,7 +731,7 @@ void QQuickCanvasItem::updatePolish()
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope);
QV4::JSCallData jsCall(scope, 1);
- jsCall->thisObject = QV4::QObjectWrapper::wrap(v4, this);
+ *jsCall->thisObject = QV4::QObjectWrapper::wrap(v4, this);
for (auto it = animationCallbacks.cbegin(), end = animationCallbacks.cend(); it != end; ++it) {
function = it.value().value();