diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-10-20 17:19:25 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-11-07 09:00:48 +0000 |
commit | e72306a6f2aeb2bddbb462c205db8fad2fb5a1a4 (patch) | |
tree | 3b83e1cead58d97c2b055283487500472ca7d698 /src | |
parent | bc5ff76e5afe6356bebb344c9a5d8b304e852f3c (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.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4dateobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4globalobject.cpp | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4include.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4jscall_p.h | 41 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4jsonobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4objectproto.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 100 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmldelayedcallqueue.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/types/qquickworkerscript.cpp | 6 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcanvasitem.cpp | 2 |
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(); |