From 6f472680ebecb3a4d700eedcf62cb423b05c4fd1 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 21 Aug 2013 17:31:22 +0200 Subject: change calling convention for JS function calls This allows faster pass through of the data if we have nested calls. Also make sure we always reserve at least QV4::Global::ReservedArgumentCount Values on the stack to avoid stack corruption. Change-Id: I42976460f1ef11a333d4adda70fba8daac66acf3 Reviewed-by: Simon Hausmann --- src/imports/localstorage/plugin.cpp | 18 ++-- src/qml/jsapi/qjsvalue.cpp | 20 +++-- src/qml/jsruntime/qv4argumentsobject.cpp | 17 ++-- src/qml/jsruntime/qv4argumentsobject_p.h | 4 +- src/qml/jsruntime/qv4arrayobject.cpp | 97 +++++++++++---------- src/qml/jsruntime/qv4arrayobject_p.h | 4 +- src/qml/jsruntime/qv4booleanobject.cpp | 8 +- src/qml/jsruntime/qv4booleanobject_p.h | 4 +- src/qml/jsruntime/qv4context.cpp | 39 +++++---- src/qml/jsruntime/qv4context_p.h | 4 +- src/qml/jsruntime/qv4dateobject.cpp | 34 ++++---- src/qml/jsruntime/qv4dateobject_p.h | 4 +- src/qml/jsruntime/qv4engine_p.h | 2 - src/qml/jsruntime/qv4errorobject.cpp | 32 +++---- src/qml/jsruntime/qv4errorobject_p.h | 16 ++-- src/qml/jsruntime/qv4functionobject.cpp | 114 +++++++++++++------------ src/qml/jsruntime/qv4functionobject_p.h | 36 ++++---- src/qml/jsruntime/qv4globalobject.cpp | 8 +- src/qml/jsruntime/qv4globalobject_p.h | 2 +- src/qml/jsruntime/qv4include.cpp | 6 +- src/qml/jsruntime/qv4jsonobject.cpp | 15 ++-- src/qml/jsruntime/qv4lookup.cpp | 54 ++++++++---- src/qml/jsruntime/qv4managed.cpp | 4 +- src/qml/jsruntime/qv4managed_p.h | 32 +++++-- src/qml/jsruntime/qv4numberobject.cpp | 12 +-- src/qml/jsruntime/qv4numberobject_p.h | 4 +- src/qml/jsruntime/qv4object.cpp | 25 +++--- src/qml/jsruntime/qv4objectproto.cpp | 16 ++-- src/qml/jsruntime/qv4objectproto_p.h | 4 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 21 ++--- src/qml/jsruntime/qv4qobjectwrapper_p.h | 4 +- src/qml/jsruntime/qv4regexpobject.cpp | 21 +++-- src/qml/jsruntime/qv4regexpobject_p.h | 4 +- src/qml/jsruntime/qv4runtime.cpp | 66 +++++++++++--- src/qml/jsruntime/qv4script.cpp | 8 +- src/qml/jsruntime/qv4sequenceobject.cpp | 10 +-- src/qml/jsruntime/qv4stringobject.cpp | 44 ++++++---- src/qml/jsruntime/qv4stringobject_p.h | 4 +- src/qml/jsruntime/qv4value_p.h | 8 +- src/qml/qml/qqmlboundsignal.cpp | 9 +- src/qml/qml/qqmlcomponent.cpp | 27 ++++-- src/qml/qml/qqmljavascriptexpression.cpp | 9 +- src/qml/qml/qqmlvmemetaobject.cpp | 7 +- src/qml/qml/qqmlxmlhttprequest.cpp | 11 ++- src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 4 +- src/qml/qml/v8/qv8engine.cpp | 6 +- src/qml/types/qqmldelegatemodel.cpp | 8 +- src/qml/types/qquickworkerscript.cpp | 20 +++-- src/quick/items/context2d/qquickcanvasitem.cpp | 8 +- 49 files changed, 549 insertions(+), 385 deletions(-) (limited to 'src') diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 0bee6d1198..6fc7d1db7f 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -341,9 +341,11 @@ static Value qmlsqldatabase_changeVersion(SimpleCallContext *ctx) ok = false; db.transaction(); - Value callbackArgs[] = { Value::fromObject(w) }; + CALLDATA(1); + d.thisObject = engine->global(); + d.args[0] = Value::fromObject(w); try { - f->call(engine->global(), callbackArgs, 1); + f->call(d); } catch (Exception &) { db.rollback(); throw; @@ -393,9 +395,11 @@ static Value qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, bool read db.transaction(); if (callback) { - Value callbackArgs[] = { Value::fromObject(w) }; + CALLDATA(1); + d.thisObject = engine->global(); + d.args[0] = Value::fromObject(w); try { - callback->call(engine->global(), callbackArgs, 1); + callback->call(d); } catch (Exception &) { w->inTransaction = false; db.rollback(); @@ -674,8 +678,10 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) db->version = version; if (created && dbcreationCallback) { - Value args[] = { Value::fromObject(db) }; - dbcreationCallback->call(engine->global(), args, 1); + CALLDATA(1); + d.thisObject = engine->global(); + d.args[0] = Value::fromObject(db); + dbcreationCallback->call(d); } args->setReturnValue(Value::fromObject(db)); diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index ec8cc2a1b3..cff760b49b 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -505,19 +505,20 @@ QJSValue QJSValue::call(const QJSValueList &args) ExecutionEngine *engine = d->engine; assert(engine); - QVarLengthArray arguments(args.length()); + CALLDATA(args.length()); + d.thisObject = Value::fromObject(engine->globalObject); for (int i = 0; i < args.size(); ++i) { if (!args.at(i).d->checkEngine(engine)) { qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); return QJSValue(); } - arguments[i] = args.at(i).d->getValue(engine); + d.args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->call(Value::fromObject(engine->globalObject), arguments.data(), arguments.size()); + result = f->call(d); } catch (Exception &e) { e.accept(ctx); result = e.value(); @@ -560,19 +561,20 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList return QJSValue(); } - QVarLengthArray arguments(args.length()); + CALLDATA(args.size()); + d.thisObject = instance.d->getValue(engine); for (int i = 0; i < args.size(); ++i) { if (!args.at(i).d->checkEngine(engine)) { qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); return QJSValue(); } - arguments[i] = args.at(i).d->getValue(engine); + d.args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->call(instance.d->getValue(engine), arguments.data(), arguments.size()); + result = f->call(d); } catch (Exception &e) { e.accept(ctx); result = e.value(); @@ -608,19 +610,19 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) ExecutionEngine *engine = d->engine; assert(engine); - QVarLengthArray arguments(args.length()); + CALLDATA(args.size()); for (int i = 0; i < args.size(); ++i) { if (!args.at(i).d->checkEngine(engine)) { qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine"); return QJSValue(); } - arguments[i] = args.at(i).d->getValue(engine); + d.args[i] = args.at(i).d->getValue(engine); } Value result; QV4::ExecutionContext *ctx = engine->current; try { - result = f->construct(arguments.data(), arguments.size()); + result = f->construct(d); } catch (Exception &e) { e.accept(ctx); result = e.value(); diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 1670f6951c..40ae29de82 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ #include +#include using namespace QV4; @@ -128,8 +129,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const if (isMapped && attrs.isData()) { if (!attrs.isGeneric()) { - Value arg = desc.value; - map.setter()->call(Value::fromObject(this), &arg, 1); + CALLDATA(1); + d.thisObject = Value::fromObject(this); + d.args[0] = desc.value; + map.setter()->call(d); } if (attrs.isWritable()) { *pd = map; @@ -144,10 +147,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction); -Value ArgumentsGetterFunction::call(Managed *getter, const Value &thisObject, Value *, int) +Value ArgumentsGetterFunction::call(Managed *getter, const CallData &d) { ArgumentsGetterFunction *g = static_cast(getter); - Object *that = thisObject.asObject(); + Object *that = d.thisObject.asObject(); if (!that) getter->engine()->current->throwTypeError(); ArgumentsObject *o = that->asArgumentsObject(); @@ -160,10 +163,10 @@ Value ArgumentsGetterFunction::call(Managed *getter, const Value &thisObject, Va DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction); -Value ArgumentsSetterFunction::call(Managed *setter, const Value &thisObject, Value *args, int argc) +Value ArgumentsSetterFunction::call(Managed *setter, const CallData &d) { ArgumentsSetterFunction *s = static_cast(setter); - Object *that = thisObject.asObject(); + Object *that = d.thisObject.asObject(); if (!that) setter->engine()->current->throwTypeError(); ArgumentsObject *o = that->asArgumentsObject(); @@ -171,7 +174,7 @@ Value ArgumentsSetterFunction::call(Managed *setter, const Value &thisObject, Va setter->engine()->current->throwTypeError(); assert(s->index < o->context->argumentCount); - o->context->arguments[s->index] = argc ? args[0] : Value::undefinedValue(); + o->context->arguments[s->index] = d.argc ? d.args[0] : Value::undefinedValue(); return Value::undefinedValue(); } diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h index 097bc4c31f..f48db1f2e6 100644 --- a/src/qml/jsruntime/qv4argumentsobject_p.h +++ b/src/qml/jsruntime/qv4argumentsobject_p.h @@ -55,7 +55,7 @@ struct ArgumentsGetterFunction: FunctionObject ArgumentsGetterFunction(ExecutionContext *scope, uint index) : FunctionObject(scope), index(index) { vtbl = &static_vtbl; } - static Value call(Managed *that, const Value &, Value *, int); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -68,7 +68,7 @@ struct ArgumentsSetterFunction: FunctionObject ArgumentsSetterFunction(ExecutionContext *scope, uint index) : FunctionObject(scope), index(index) { vtbl = &static_vtbl; } - static Value call(Managed *that, const Value &, Value *, int); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index d7f4babbb2..c316a3196e 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -52,25 +52,25 @@ ArrayCtor::ArrayCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value ArrayCtor::construct(Managed *m, Value *argv, int argc) +Value ArrayCtor::construct(Managed *m, const CallData &d) { ExecutionEngine *v4 = m->engine(); ArrayObject *a = v4->newArrayObject(); uint len; - if (argc == 1 && argv[0].isNumber()) { + if (d.argc == 1 && d.args[0].isNumber()) { bool ok; - len = argv[0].asArrayLength(&ok); + len = d.args[0].asArrayLength(&ok); if (!ok) - v4->current->throwRangeError(argv[0]); + v4->current->throwRangeError(d.args[0]); if (len < 0x1000) a->arrayReserve(len); } else { - len = argc; + len = d.argc; a->arrayReserve(len); for (unsigned int i = 0; i < len; ++i) - a->arrayData[i].value = argv[i]; + a->arrayData[i].value = d.args[i]; a->arrayDataLen = len; } a->setArrayLengthUnchecked(len); @@ -78,9 +78,9 @@ Value ArrayCtor::construct(Managed *m, Value *argv, int argc) return Value::fromObject(a); } -Value ArrayCtor::call(Managed *that, const Value &, Value *argv, int argc) +Value ArrayCtor::call(Managed *that, const CallData &d) { - return construct(that, argv, argc); + return construct(that, d); } ArrayPrototype::ArrayPrototype(ExecutionContext *context) @@ -628,11 +628,12 @@ Value ArrayPrototype::method_every(SimpleCallContext *ctx) if (!exists) continue; - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = Value::fromObject(instance); - Value r = callback->call(thisArg, args, 3); + CALLDATA(3); + d.args[0] = v; + d.args[1] = Value::fromDouble(k); + d.args[2] = Value::fromObject(instance); + d.thisObject = thisArg; + Value r = callback->call(d); ok = r.toBoolean(); } return Value::fromBoolean(ok); @@ -656,11 +657,12 @@ Value ArrayPrototype::method_some(SimpleCallContext *ctx) if (!exists) continue; - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = Value::fromObject(instance); - Value r = callback->call(thisArg, args, 3); + CALLDATA(3); + d.args[0] = v; + d.args[1] = Value::fromDouble(k); + d.args[2] = Value::fromObject(instance); + d.thisObject = thisArg; + Value r = callback->call(d); if (r.toBoolean()) return Value::fromBoolean(true); } @@ -685,11 +687,12 @@ Value ArrayPrototype::method_forEach(SimpleCallContext *ctx) if (!exists) continue; - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = Value::fromObject(instance); - callback->call(thisArg, args, 3); + CALLDATA(3); + d.args[0] = v; + d.args[1] = Value::fromDouble(k); + d.args[2] = Value::fromObject(instance); + d.thisObject = thisArg; + callback->call(d); } return Value::undefinedValue(); } @@ -716,11 +719,12 @@ Value ArrayPrototype::method_map(SimpleCallContext *ctx) if (!exists) continue; - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = Value::fromObject(instance); - Value mapped = callback->call(thisArg, args, 3); + CALLDATA(3); + d.args[0] = v; + d.args[1] = Value::fromDouble(k); + d.args[2] = Value::fromObject(instance); + d.thisObject = thisArg; + Value mapped = callback->call(d); a->arraySet(k, mapped); } return Value::fromObject(a); @@ -748,11 +752,12 @@ Value ArrayPrototype::method_filter(SimpleCallContext *ctx) if (!exists) continue; - Value args[3]; - args[0] = v; - args[1] = Value::fromDouble(k); - args[2] = Value::fromObject(instance); - Value selected = callback->call(thisArg, args, 3); + CALLDATA(3); + d.args[0] = v; + d.args[1] = Value::fromDouble(k); + d.args[2] = Value::fromObject(instance); + d.thisObject = thisArg; + Value selected = callback->call(d); if (selected.toBoolean()) { a->arraySet(to, v); ++to; @@ -791,12 +796,13 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx) bool kPresent; Value v = instance->getIndexed(k, &kPresent); if (kPresent) { - Value args[4]; - args[0] = acc; - args[1] = v; - args[2] = Value::fromDouble(k); - args[3] = Value::fromObject(instance); - acc = callback->call(Value::undefinedValue(), args, 4); + CALLDATA(4); + d.args[0] = acc; + d.args[1] = v; + d.args[2] = Value::fromDouble(k); + d.args[3] = Value::fromObject(instance); + d.thisObject = Value::undefinedValue(); + acc = callback->call(d); } ++k; } @@ -839,12 +845,13 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx) bool kPresent; Value v = instance->getIndexed(k - 1, &kPresent); if (kPresent) { - Value args[4]; - args[0] = acc; - args[1] = v; - args[2] = Value::fromDouble(k - 1); - args[3] = Value::fromObject(instance); - acc = callback->call(Value::undefinedValue(), args, 4); + CALLDATA(4); + d.args[0] = acc; + d.args[1] = v; + d.args[2] = Value::fromDouble(k - 1); + d.args[3] = Value::fromObject(instance); + d.thisObject = Value::undefinedValue(); + acc = callback->call(d); } --k; } diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h index 13c3882f4f..f5c256669f 100644 --- a/src/qml/jsruntime/qv4arrayobject_p.h +++ b/src/qml/jsruntime/qv4arrayobject_p.h @@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject { ArrayCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *m, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp index 24678d23dc..25c105210a 100644 --- a/src/qml/jsruntime/qv4booleanobject.cpp +++ b/src/qml/jsruntime/qv4booleanobject.cpp @@ -51,15 +51,15 @@ BooleanCtor::BooleanCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value BooleanCtor::construct(Managed *m, Value *args, int argc) +Value BooleanCtor::construct(Managed *m, const CallData &d) { - bool n = argc ? args[0].toBoolean() : false; + bool n = d.argc ? d.args[0].toBoolean() : false; return Value::fromObject(m->engine()->newBooleanObject(Value::fromBoolean(n))); } -Value BooleanCtor::call(Managed *, const Value &, Value *argv, int argc) +Value BooleanCtor::call(Managed *, const CallData &d) { - bool value = argc ? argv[0].toBoolean() : 0; + bool value = d.argc ? d.args[0].toBoolean() : 0; return Value::fromBoolean(value); } diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h index 3e5e7663f2..0cdcdec1f1 100644 --- a/src/qml/jsruntime/qv4booleanobject_p.h +++ b/src/qml/jsruntime/qv4booleanobject_p.h @@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject { BooleanCtor(ExecutionContext *scope); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 7353d69d32..7d7f5dda25 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -51,7 +51,7 @@ using namespace QV4; -CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, const Value &thisObject, Value *args, int argc) +CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, const CallData &d) { CallContext *c = (CallContext *)stackSpace; #ifndef QT_NO_DEBUG @@ -63,10 +63,10 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject * c->initBaseContext(Type_CallContext, engine, this); c->function = function; - c->arguments = args; - c->realArgumentCount = argc; - c->argumentCount = argc; - c->thisObject = thisObject; + c->arguments = d.args; + c->realArgumentCount = d.argc; + c->argumentCount = d.argc; + c->thisObject = d.thisObject; c->strictMode = function->strictMode; c->marked = false; @@ -89,27 +89,30 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject * if (function->varCount) std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue()); - if (argc < function->formalParameterCount) { - std::fill(c->arguments + argc, c->arguments + function->formalParameterCount, Value::undefinedValue()); + if (d.argc < function->formalParameterCount) { +#ifndef QT_NO_DEBUG + Q_ASSERT(function->formalParameterCount <= QV4::Global::ReservedArgumentCount); +#endif + std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue()); c->argumentCount = function->formalParameterCount; } return c; } -CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Value &thisObject, Value *args, int argc) +CallContext *ExecutionContext::newCallContext(FunctionObject *function, const CallData &d) { - CallContext *c = static_cast(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, argc))); + CallContext *c = static_cast(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, d.argc))); engine->current = c; c->initBaseContext(Type_CallContext, engine, this); c->function = function; - c->arguments = args; - c->realArgumentCount = argc; - c->argumentCount = argc; - c->thisObject = thisObject; + c->arguments = d.args; + c->realArgumentCount = d.argc; + c->argumentCount = d.argc; + c->thisObject = d.thisObject; c->strictMode = function->strictMode; c->marked = false; @@ -132,12 +135,12 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Va if (function->varCount) std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue()); - c->argumentCount = qMax((uint)argc, function->formalParameterCount); + c->argumentCount = qMax((uint)d.argc, function->formalParameterCount); c->arguments = c->locals + function->varCount; - if (argc) - ::memcpy(c->arguments, args, argc * sizeof(Value)); - if (argc < function->formalParameterCount) - std::fill(c->arguments + argc, c->arguments + function->formalParameterCount, Value::undefinedValue()); + if (d.argc) + ::memcpy(c->arguments, d.args, c->realArgumentCount * sizeof(Value)); + if (d.argc < function->formalParameterCount) + std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue()); return c; } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 0c1dfb1d71..331c5aa990 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -114,8 +114,8 @@ struct Q_QML_EXPORT ExecutionContext interpreterInstructionPointer = 0; } - CallContext *newCallContext(void *stackSpace, FunctionObject *f, const QV4::Value &thisObject, QV4::Value *args, int argc); - CallContext *newCallContext(FunctionObject *f, const QV4::Value &thisObject, QV4::Value *args, int argc); + CallContext *newCallContext(void *stackSpace, FunctionObject *f, const CallData &d); + CallContext *newCallContext(FunctionObject *f, const CallData &d); WithContext *newWithContext(Object *with); CatchContext *newCatchContext(String* exceptionVarName, const QV4::Value &exceptionValue); CallContext *newQmlContext(FunctionObject *f, Object *qml); diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 47730f2f2e..87d93add6e 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -659,15 +659,15 @@ DateCtor::DateCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value DateCtor::construct(Managed *m, Value *args, int argc) +Value DateCtor::construct(Managed *m, const CallData &d) { double t = 0; - if (argc == 0) + if (d.argc == 0) t = currentTime(); - else if (argc == 1) { - Value arg = args[0]; + else if (d.argc == 1) { + Value arg = d.args[0]; if (DateObject *d = arg.asDateObject()) arg = d->value; else @@ -679,25 +679,25 @@ Value DateCtor::construct(Managed *m, Value *args, int argc) t = TimeClip(arg.toNumber()); } - else { // argc > 1 - double year = args[0].toNumber(); - double month = args[1].toNumber(); - double day = argc >= 3 ? args[2].toNumber() : 1; - double hours = argc >= 4 ? args[3].toNumber() : 0; - double mins = argc >= 5 ? args[4].toNumber() : 0; - double secs = argc >= 6 ? args[5].toNumber() : 0; - double ms = argc >= 7 ? args[6].toNumber() : 0; + else { // d.argc > 1 + double year = d.args[0].toNumber(); + double month = d.args[1].toNumber(); + double day = d.argc >= 3 ? d.args[2].toNumber() : 1; + double hours = d.argc >= 4 ? d.args[3].toNumber() : 0; + double mins = d.argc >= 5 ? d.args[4].toNumber() : 0; + double secs = d.argc >= 6 ? d.args[5].toNumber() : 0; + double ms = d.argc >= 7 ? d.args[6].toNumber() : 0; if (year >= 0 && year <= 99) year += 1900; t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); t = TimeClip(UTC(t)); } - Object *d = m->engine()->newDateObject(Value::fromDouble(t)); - return Value::fromObject(d); + Object *o = m->engine()->newDateObject(Value::fromDouble(t)); + return Value::fromObject(o); } -Value DateCtor::call(Managed *m, const Value &, Value *, int) +Value DateCtor::call(Managed *m, const CallData &) { double t = currentTime(); return Value::fromString(m->engine()->current, ToString(t)); @@ -1306,7 +1306,9 @@ Value DatePrototype::method_toJSON(SimpleCallContext *ctx) if (!toIso) ctx->throwTypeError(); - return toIso->call(ctx->thisObject, 0, 0); + CALLDATA(0); + d.thisObject = ctx->thisObject; + return toIso->call(d); } void DatePrototype::timezoneUpdated() diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h index 4e833e143f..89ca057a1b 100644 --- a/src/qml/jsruntime/qv4dateobject_p.h +++ b/src/qml/jsruntime/qv4dateobject_p.h @@ -63,8 +63,8 @@ struct DateCtor: FunctionObject { DateCtor(ExecutionContext *scope); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 0b6756466c..8f6e47e5f1 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -314,8 +314,6 @@ inline void ExecutionEngine::pushContext(SimpleCallContext *context) inline ExecutionContext *ExecutionEngine::popContext() { - CallContext *c = current->asCallContext(); - current = current->parent; return current; } diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp index 68f6f56a18..6c7c290452 100644 --- a/src/qml/jsruntime/qv4errorobject.cpp +++ b/src/qml/jsruntime/qv4errorobject.cpp @@ -242,14 +242,14 @@ ErrorCtor::ErrorCtor(ExecutionContext *scope, String *name) vtbl = &static_vtbl; } -Value ErrorCtor::construct(Managed *m, Value *args, int argc) +Value ErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(m->engine()->newErrorObject(argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(m->engine()->newErrorObject(d.argc ? d.args[0] : Value::undefinedValue())); } -Value ErrorCtor::call(Managed *that, const Value &, Value *args, int argc) +Value ErrorCtor::call(Managed *that, const CallData &d) { - return that->construct(args, argc); + return that->construct(d); } EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope) @@ -258,9 +258,9 @@ EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value EvalErrorCtor::construct(Managed *m, Value *args, int argc) +Value EvalErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope) @@ -269,9 +269,9 @@ RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value RangeErrorCtor::construct(Managed *m, Value *args, int argc) +Value RangeErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope) @@ -280,9 +280,9 @@ ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value ReferenceErrorCtor::construct(Managed *m, Value *args, int argc) +Value ReferenceErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope) @@ -291,9 +291,9 @@ SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value SyntaxErrorCtor::construct(Managed *m, Value *args, int argc) +Value SyntaxErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope) @@ -302,9 +302,9 @@ TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value TypeErrorCtor::construct(Managed *m, Value *args, int argc) +Value TypeErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } URIErrorCtor::URIErrorCtor(ExecutionContext *scope) @@ -313,9 +313,9 @@ URIErrorCtor::URIErrorCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value URIErrorCtor::construct(Managed *m, Value *args, int argc) +Value URIErrorCtor::construct(Managed *m, const CallData &d) { - return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), argc ? args[0] : Value::undefinedValue())); + return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue())); } void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *obj) diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h index 798f86fdc6..c51023205f 100644 --- a/src/qml/jsruntime/qv4errorobject_p.h +++ b/src/qml/jsruntime/qv4errorobject_p.h @@ -113,8 +113,8 @@ struct ErrorCtor: FunctionObject ErrorCtor(ExecutionContext *scope); ErrorCtor(ExecutionContext *scope, String *name); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -124,7 +124,7 @@ struct EvalErrorCtor: ErrorCtor { EvalErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -134,7 +134,7 @@ struct RangeErrorCtor: ErrorCtor { RangeErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -144,7 +144,7 @@ struct ReferenceErrorCtor: ErrorCtor { ReferenceErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -154,7 +154,7 @@ struct SyntaxErrorCtor: ErrorCtor { SyntaxErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -164,7 +164,7 @@ struct TypeErrorCtor: ErrorCtor { TypeErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -174,7 +174,7 @@ struct URIErrorCtor: ErrorCtor { URIErrorCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); + static Value construct(Managed *m, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 950a5a5dbf..a4533edc9c 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -102,7 +102,8 @@ FunctionObject::~FunctionObject() Value FunctionObject::newInstance() { - return construct(0, 0); + CALLDATA(0); + return construct(d); } bool FunctionObject::hasInstance(Managed *that, const Value &value) @@ -130,7 +131,7 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value) return false; } -Value FunctionObject::construct(Managed *that, Value *, int) +Value FunctionObject::construct(Managed *that, const CallData &) { FunctionObject *f = static_cast(that); ExecutionEngine *v4 = f->engine(); @@ -142,7 +143,7 @@ Value FunctionObject::construct(Managed *that, Value *, int) return Value::fromObject(obj); } -Value FunctionObject::call(Managed *, const Value &, Value *, int) +Value FunctionObject::call(Managed *, const CallData &) { return Value::undefinedValue(); } @@ -181,7 +182,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope) } // 15.3.2 -Value FunctionCtor::construct(Managed *that, Value *args, int argc) +Value FunctionCtor::construct(Managed *that, const CallData &d) { FunctionCtor *f = static_cast(that); MemoryManager::GCBlocker gcBlocker(f->engine()->memoryManager); @@ -189,13 +190,13 @@ Value FunctionCtor::construct(Managed *that, Value *args, int argc) ExecutionContext *ctx = f->engine()->current; QString arguments; QString body; - if (argc > 0) { - for (uint i = 0; i < argc - 1; ++i) { + if (d.argc > 0) { + for (uint i = 0; i < d.argc - 1; ++i) { if (i) arguments += QLatin1String(", "); - arguments += args[i].toString(ctx)->toQString(); + arguments += d.args[i].toString(ctx)->toQString(); } - body = args[argc - 1].toString(ctx)->toQString(); + body = d.args[d.argc - 1].toString(ctx)->toQString(); } QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}"); @@ -229,9 +230,9 @@ Value FunctionCtor::construct(Managed *that, Value *args, int argc) } // 15.3.1: This is equivalent to new Function(...) -Value FunctionCtor::call(Managed *that, const Value &, Value *args, int argc) +Value FunctionCtor::call(Managed *that, const CallData &d) { - return construct(that, args, argc); + return construct(that, d); } FunctionPrototype::FunctionPrototype(ExecutionContext *ctx) @@ -281,28 +282,27 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx) } quint32 len = arr ? arr->get(ctx->engine->id_length).toUInt32() : 0; - QVarLengthArray args(len); + CALLDATA(len); for (quint32 i = 0; i < len; ++i) - args[i] = arr->getIndexed(i); - - - return o->call(thisArg, len ? args.data() : 0, len); + d.args[i] = arr->getIndexed(i); + d.thisObject = thisArg; + return o->call(d); } Value FunctionPrototype::method_call(SimpleCallContext *ctx) { Value thisArg = ctx->argument(0); - QVarLengthArray args(ctx->argumentCount ? ctx->argumentCount - 1 : 0); - if (ctx->argumentCount) - qCopy(ctx->arguments + 1, - ctx->arguments + ctx->argumentCount, args.begin()); - FunctionObject *o = ctx->thisObject.asFunctionObject(); if (!o) ctx->throwTypeError(); - return o->call(thisArg, args.data(), args.size()); + CALLDATA(ctx->argumentCount ? ctx->argumentCount - 1 : 0); + if (ctx->argumentCount) + qCopy(ctx->arguments + 1, + ctx->arguments + ctx->argumentCount, d.args); + d.thisObject = thisArg; + return o->call(d); } Value FunctionPrototype::method_bind(SimpleCallContext *ctx) @@ -368,7 +368,7 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) } } -Value ScriptFunction::construct(Managed *that, Value *args, int argc) +Value ScriptFunction::construct(Managed *that, const CallData &d) { ScriptFunction *f = static_cast(that); ExecutionEngine *v4 = f->engine(); @@ -378,7 +378,9 @@ Value ScriptFunction::construct(Managed *that, Value *args, int argc) obj->prototype = proto.objectValue(); ExecutionContext *context = v4->current; - ExecutionContext *ctx = context->newCallContext(f, Value::fromObject(obj), args, argc); + CallData dd = d; + dd.thisObject = Value::fromObject(obj); + ExecutionContext *ctx = context->newCallContext(f, dd); Value result; try { @@ -394,18 +396,18 @@ Value ScriptFunction::construct(Managed *that, Value *args, int argc) return Value::fromObject(obj); } -Value ScriptFunction::call(Managed *that, const Value &thisObject, Value *args, int argc) +Value ScriptFunction::call(Managed *that, const CallData &d) { ScriptFunction *f = static_cast(that); void *stackSpace; ExecutionContext *context = f->engine()->current; - ExecutionContext *ctx = context->newCallContext(f, thisObject, args, argc); + ExecutionContext *ctx = context->newCallContext(f, d); - if (!f->strictMode && !thisObject.isObject()) { - if (thisObject.isUndefined() || thisObject.isNull()) { + if (!f->strictMode && !d.thisObject.isObject()) { + if (d.thisObject.isUndefined() || d.thisObject.isNull()) { ctx->thisObject = Value::fromObject(f->engine()->globalObject); } else { - ctx->thisObject = Value::fromObject(thisObject.toObject(context)); + ctx->thisObject = Value::fromObject(d.thisObject.toObject(context)); } } @@ -460,7 +462,7 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu } } -Value SimpleScriptFunction::construct(Managed *that, Value *args, int argc) +Value SimpleScriptFunction::construct(Managed *that, const CallData &d) { SimpleScriptFunction *f = static_cast(that); ExecutionEngine *v4 = f->engine(); @@ -471,7 +473,9 @@ Value SimpleScriptFunction::construct(Managed *that, Value *args, int argc) ExecutionContext *context = v4->current; void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f)); - ExecutionContext *ctx = context->newCallContext(stackSpace, f, Value::fromObject(obj), args, argc); + CallData dd = d; + dd.thisObject = Value::fromObject(obj); + ExecutionContext *ctx = context->newCallContext(stackSpace, f, dd); Value result; try { @@ -487,18 +491,18 @@ Value SimpleScriptFunction::construct(Managed *that, Value *args, int argc) return Value::fromObject(obj); } -Value SimpleScriptFunction::call(Managed *that, const Value &thisObject, Value *args, int argc) +Value SimpleScriptFunction::call(Managed *that, const CallData &d) { SimpleScriptFunction *f = static_cast(that); void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f)); ExecutionContext *context = f->engine()->current; - ExecutionContext *ctx = context->newCallContext(stackSpace, f, thisObject, args, argc); + ExecutionContext *ctx = context->newCallContext(stackSpace, f, d); - if (!f->strictMode && !thisObject.isObject()) { - if (thisObject.isUndefined() || thisObject.isNull()) { + if (!f->strictMode && !d.thisObject.isObject()) { + if (d.thisObject.isUndefined() || d.thisObject.isNull()) { ctx->thisObject = Value::fromObject(f->engine()->globalObject); } else { - ctx->thisObject = Value::fromObject(thisObject.toObject(context)); + ctx->thisObject = Value::fromObject(d.thisObject.toObject(context)); } } @@ -526,13 +530,13 @@ BuiltinFunctionOld::BuiltinFunctionOld(ExecutionContext *scope, String *name, Va isBuiltinFunction = true; } -Value BuiltinFunctionOld::construct(Managed *f, Value *, int) +Value BuiltinFunctionOld::construct(Managed *f, const CallData &d) { f->engine()->current->throwTypeError(); return Value::undefinedValue(); } -Value BuiltinFunctionOld::call(Managed *that, const Value &thisObject, Value *args, int argc) +Value BuiltinFunctionOld::call(Managed *that, const CallData &d) { BuiltinFunctionOld *f = static_cast(that); ExecutionEngine *v4 = f->engine(); @@ -541,9 +545,9 @@ Value BuiltinFunctionOld::call(Managed *that, const Value &thisObject, Value *ar SimpleCallContext ctx; ctx.initSimpleCallContext(f->scope->engine); ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? - ctx.thisObject = thisObject; - ctx.arguments = args; - ctx.argumentCount = argc; + ctx.thisObject = d.thisObject; + ctx.arguments = d.args; + ctx.argumentCount = d.argc; v4->pushContext(&ctx); Value result; @@ -558,7 +562,7 @@ Value BuiltinFunctionOld::call(Managed *that, const Value &thisObject, Value *ar return result; } -Value IndexedBuiltinFunction::call(Managed *that, const Value &thisObject, Value *args, int argc) +Value IndexedBuiltinFunction::call(Managed *that, const CallData &d) { IndexedBuiltinFunction *f = static_cast(that); ExecutionEngine *v4 = f->engine(); @@ -567,9 +571,9 @@ Value IndexedBuiltinFunction::call(Managed *that, const Value &thisObject, Value SimpleCallContext ctx; ctx.initSimpleCallContext(f->scope->engine); ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context? - ctx.thisObject = thisObject; - ctx.arguments = args; - ctx.argumentCount = argc; + ctx.thisObject = d.thisObject; + ctx.arguments = d.args; + ctx.argumentCount = d.argc; v4->pushContext(&ctx); Value result; @@ -612,24 +616,24 @@ void BoundFunction::destroy(Managed *that) static_cast(that)->~BoundFunction(); } -Value BoundFunction::call(Managed *that, const Value &, Value *args, int argc) +Value BoundFunction::call(Managed *that, const CallData &dd) { BoundFunction *f = static_cast(that); - Value *newArgs = static_cast(alloca(sizeof(Value)*(f->boundArgs.size() + argc))); - memcpy(newArgs, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); - memcpy(newArgs + f->boundArgs.size(), args, argc*sizeof(Value)); - return f->target->call(f->boundThis, newArgs, f->boundArgs.size() + argc); + CALLDATA(f->boundArgs.size() + dd.argc); + d.thisObject = f->boundThis; + memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); + memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value)); + return f->target->call(d); } -Value BoundFunction::construct(Managed *that, Value *args, int argc) +Value BoundFunction::construct(Managed *that, const CallData &dd) { BoundFunction *f = static_cast(that); - Value *newArgs = static_cast(alloca(sizeof(Value)*(f->boundArgs.size() + argc))); - memcpy(newArgs, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); - memcpy(newArgs + f->boundArgs.size(), args, argc*sizeof(Value)); - - return f->target->construct(newArgs, f->boundArgs.size() + argc); + CALLDATA(f->boundArgs.size() + dd.argc); + memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value)); + memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value)); + return f->target->construct(d); } bool BoundFunction::hasInstance(Managed *that, const Value &value) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 89e2b14ca7..fdfb1e6a2b 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -112,13 +112,13 @@ struct Q_QML_EXPORT FunctionObject: Object { Value newInstance(); - static Value construct(Managed *that, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); - inline Value construct(Value *args, int argc) { - return vtbl->construct(this, args, argc); + static Value construct(Managed *that, const CallData &); + static Value call(Managed *that, const CallData &d); + inline Value construct(const CallData &d) { + return vtbl->construct(this, d); } - inline Value call(const Value &thisObject, Value *args, int argc) { - return vtbl->call(this, thisObject, args, argc); + inline Value call(const CallData &d) { + return vtbl->call(this, d); } static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function); @@ -135,8 +135,8 @@ struct FunctionCtor: FunctionObject { FunctionCtor(ExecutionContext *scope); - static Value construct(Managed *that, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *that, const CallData &); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -158,8 +158,8 @@ struct BuiltinFunctionOld: FunctionObject { BuiltinFunctionOld(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *)); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -181,21 +181,21 @@ struct IndexedBuiltinFunction: FunctionObject isBuiltinFunction = true; } - static Value construct(Managed *m, Value *, int) + static Value construct(Managed *m, const CallData &) { m->engine()->current->throwTypeError(); return Value::undefinedValue(); } - static Value call(Managed *that, const Value &thisObject, Value *args, int argc); + static Value call(Managed *that, const CallData &d); }; struct ScriptFunction: FunctionObject { ScriptFunction(ExecutionContext *scope, Function *function); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -204,8 +204,8 @@ protected: struct SimpleScriptFunction: FunctionObject { SimpleScriptFunction(ExecutionContext *scope, Function *function); - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; @@ -220,8 +220,8 @@ struct BoundFunction: FunctionObject { ~BoundFunction() {} - static Value construct(Managed *, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *, const CallData &d); + static Value call(Managed *that, const CallData &d); static const ManagedVTable static_vtbl; static void destroy(Managed *); diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index 53d43dbc7c..3b06a6d884 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -390,7 +390,9 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d if (strictMode) { FunctionObject *e = FunctionObject::creatScriptFunction(ctx, function); - return e->call(ctx->thisObject, 0, 0); + CALLDATA(0); + d.thisObject = ctx->thisObject; + return e->call(d); } ExecutionContext::EvalCode evalCode; @@ -436,10 +438,10 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d } -Value EvalFunction::call(Managed *that, const Value &thisObject, Value *args, int argc) +Value EvalFunction::call(Managed *that, const CallData &d) { // indirect call - return static_cast(that)->evalCall(thisObject, args, argc, false); + return static_cast(that)->evalCall(d.thisObject, d.args, d.argc, false); } diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h index 11d034b5b4..4ac531c27b 100644 --- a/src/qml/jsruntime/qv4globalobject_p.h +++ b/src/qml/jsruntime/qv4globalobject_p.h @@ -55,7 +55,7 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject Value evalCall(Value thisObject, Value *args, int argc, bool directCall); using Managed::construct; - static Value call(Managed *that, const Value &, Value *, int); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 4fd7bb14c7..9068d573f6 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -102,10 +102,12 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status) if (!f) return; - QV4::Value args[] = { status }; QV4::ExecutionContext *ctx = f->engine()->current; try { - f->call(QV4::Value::fromObject(f->engine()->globalObject), args, 1); + CALLDATA(1); + d.thisObject = QV4::Value::fromObject(f->engine()->globalObject); + d.args[0] = status; + f->call(d); } catch (QV4::Exception &e) { e.accept(ctx); } diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index e5a8582d19..68a4c5ca71 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -702,8 +702,10 @@ QString Stringify::Str(const QString &key, Value value) if (Object *o = value.asObject()) { FunctionObject *toJSON = o->get(ctx->engine->newString(QStringLiteral("toJSON"))).asFunctionObject(); if (toJSON) { - Value arg = Value::fromString(ctx, key); - value = toJSON->call(value, &arg, 1); + CALLDATA(1); + d.thisObject = value; + d.args[0] = Value::fromString(ctx, key); + value = toJSON->call(d); } } @@ -711,10 +713,11 @@ QString Stringify::Str(const QString &key, Value value) Object *holder = ctx->engine->newObject(); Value holderValue = Value::fromObject(holder); holder->put(ctx, QString(), value); - Value args[2]; - args[0] = Value::fromString(ctx, key); - args[1] = value; - value = replacerFunction->call(holderValue, args, 2); + CALLDATA(2); + d.args[0] = Value::fromString(ctx, key); + d.args[1] = value; + d.thisObject = holderValue; + value = replacerFunction->call(d); } if (Object *o = value.asObject()) { diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 345611d46c..b7a6f73822 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -157,10 +157,13 @@ void Lookup::getterAccessor0(Lookup *l, Value *result, const Value &object) if (l->classList[0] == o->internalClass) { Value res; FunctionObject *getter = o->memberData[l->index].getter(); - if (!getter) + if (!getter) { res = Value::undefinedValue(); - else - res = getter->call(object, 0, 0); + } else { + CALLDATA(0); + d.thisObject = object; + res = getter->call(d); + } if (result) *result = res; return; @@ -177,10 +180,13 @@ void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object) l->classList[1] == o->prototype->internalClass) { Value res; FunctionObject *getter = o->prototype->memberData[l->index].getter(); - if (!getter) + if (!getter) { res = Value::undefinedValue(); - else - res = getter->call(object, 0, 0); + } else { + CALLDATA(0); + d.thisObject = object; + res = getter->call(d); + } if (result) *result = res; return; @@ -200,10 +206,13 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object) if (l->classList[2] == o->internalClass) { Value res; FunctionObject *getter = o->memberData[l->index].getter(); - if (!getter) + if (!getter) { res = Value::undefinedValue(); - else - res = getter->call(object, 0, 0); + } else { + CALLDATA(0); + d.thisObject = object; + res = getter->call(d); + } if (result) *result = res; return; @@ -292,10 +301,13 @@ void Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *resu Object *o = ctx->engine->globalObject; if (l->classList[0] == o->internalClass) { FunctionObject *getter = o->memberData[l->index].getter(); - if (!getter) + if (!getter) { *result = Value::undefinedValue(); - else - *result = getter->call(Value::undefinedValue(), 0, 0); + } else { + CALLDATA(0); + d.thisObject = Value::undefinedValue(); + *result = getter->call(d); + } return; } l->globalGetter = globalGetterGeneric; @@ -308,10 +320,13 @@ void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *resu if (l->classList[0] == o->internalClass && l->classList[1] == o->prototype->internalClass) { FunctionObject *getter = o->prototype->memberData[l->index].getter(); - if (!getter) + if (!getter) { *result = Value::undefinedValue(); - else - *result = getter->call(Value::undefinedValue(), 0, 0); + } else { + CALLDATA(0); + d.thisObject = Value::undefinedValue(); + *result = getter->call(d); + } return; } l->globalGetter = globalGetterGeneric; @@ -327,10 +342,13 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu o = o->prototype; if (l->classList[2] == o->internalClass) { FunctionObject *getter = o->memberData[l->index].getter(); - if (!getter) + if (!getter) { *result = Value::undefinedValue(); - else - *result = getter->call(Value::undefinedValue(), 0, 0); + } else { + CALLDATA(0); + d.thisObject = Value::undefinedValue(); + *result = getter->call(d); + } return; } } diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp index 19adb354e3..955d12a3d0 100644 --- a/src/qml/jsruntime/qv4managed.cpp +++ b/src/qml/jsruntime/qv4managed.cpp @@ -176,12 +176,12 @@ bool Managed::hasInstance(Managed *m, const Value &) m->engine()->current->throwTypeError(); } -Value Managed::construct(Managed *m, Value *, int) +Value Managed::construct(Managed *m, const CallData &) { m->engine()->current->throwTypeError(); } -Value Managed::call(Managed *m, const Value &, Value *, int) +Value Managed::call(Managed *m, const CallData &) { m->engine()->current->throwTypeError(); } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 227cd4bdb0..b77b1cd638 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -74,10 +74,30 @@ struct GCDeletable bool lastCall; }; +struct CallData +{ + Value thisObject; + Value *args; + int argc; +}; + +#ifdef QT_NO_DEBUG +#define CALLDATA(argc_) \ + QV4::CallData d; \ + d.argc = argc_; \ + d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value)) +#else +#define CALLDATA(argc_) \ + QV4::CallData d; \ + d.argc = argc_; \ + d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value)); \ + for (int iii = 0; iii < qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount); ++iii) d.args[iii] = QV4::Value::undefinedValue() +#endif + struct ManagedVTable { - Value (*call)(Managed *, const Value &thisObject, Value *args, int argc); - Value (*construct)(Managed *, Value *args, int argc); + Value (*call)(Managed *, const CallData &data); + Value (*construct)(Managed *, const CallData &data); void (*markObjects)(Managed *); void (*destroy)(Managed *); void (*collectDeletables)(Managed *, GCDeletable **deletable); @@ -237,8 +257,8 @@ public: inline bool hasInstance(const Value &v) { return vtbl->hasInstance(this, v); } - Value construct(Value *args, int argc); - Value call(const Value &thisObject, Value *args, int argc); + Value construct(const CallData &d); + Value call(const CallData &d); Value get(String *name, bool *hasProperty = 0); Value getIndexed(uint index, bool *hasProperty = 0); void put(String *name, const Value &value) @@ -266,8 +286,8 @@ public: static void destroy(Managed *that) { that->_data = 0; } static bool hasInstance(Managed *that, const Value &value); - static Value construct(Managed *m, Value *, int); - static Value call(Managed *m, const Value &, Value *, int); + static Value construct(Managed *m, const CallData &d); + static Value call(Managed *m, const CallData &); static void getLookup(Managed *m, Lookup *, Value *); static void setLookup(Managed *m, Lookup *l, const Value &v); static bool isEqualTo(Managed *m, Managed *other); diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index 6d3b6220cc..88c61489db 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -56,16 +56,16 @@ NumberCtor::NumberCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value NumberCtor::construct(Managed *m, Value *args, int argc) +Value NumberCtor::construct(Managed *m, const CallData &d) { - double d = argc ? args[0].toNumber() : 0.; - return Value::fromObject(m->engine()->newNumberObject(Value::fromDouble(d))); + double dbl = d.argc ? d.args[0].toNumber() : 0.; + return Value::fromObject(m->engine()->newNumberObject(Value::fromDouble(dbl))); } -Value NumberCtor::call(Managed *, const Value &, Value *argv, int argc) +Value NumberCtor::call(Managed *, const CallData &d) { - double d = argc ? argv[0].toNumber() : 0.; - return Value::fromDouble(d); + double dbl = d.argc ? d.args[0].toNumber() : 0.; + return Value::fromDouble(dbl); } void NumberPrototype::init(ExecutionContext *ctx, const Value &ctor) diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index 0c06451c98..224840ebb7 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject { NumberCtor(ExecutionContext *scope); - static Value construct(Managed *that, Value *args, int argc); - static Value call(Managed *, const Value &, Value *, int); + static Value construct(Managed *that, const CallData &d); + static Value call(Managed *, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 01be2d7091..ab33764142 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -135,16 +135,19 @@ Value Object::getValue(const Value &thisObject, const Property *p, PropertyAttri if (!getter) return Value::undefinedValue(); - return getter->call(thisObject, 0, 0); + CALLDATA(0); + d.thisObject = thisObject; + return getter->call(d); } void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value) { if (attrs.isAccessor()) { if (pd->set) { - Value args[1]; - args[0] = value; - pd->set->call(Value::fromObject(this), args, 1); + CALLDATA(1); + d.args[0] = value; + d.thisObject = Value::fromObject(this); + pd->set->call(d); return; } goto reject; @@ -773,9 +776,10 @@ void Object::internalPut(String *name, const Value &value) if (pd && attrs.isAccessor()) { assert(pd->setter() != 0); - Value args[1]; - args[0] = value; - pd->setter()->call(Value::fromObject(this), args, 1); + CALLDATA(1); + d.args[0] = value; + d.thisObject = Value::fromObject(this); + pd->setter()->call(d); return; } @@ -850,9 +854,10 @@ void Object::internalPutIndexed(uint index, const Value &value) if (pd && attrs.isAccessor()) { assert(pd->setter() != 0); - Value args[1]; - args[0] = value; - pd->setter()->call(Value::fromObject(this), args, 1); + CALLDATA(1); + d.args[0] = value; + d.thisObject = Value::fromObject(this); + pd->setter()->call(d); return; } diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index add26867a8..ec60a9b343 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -78,25 +78,25 @@ ObjectCtor::ObjectCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value ObjectCtor::construct(Managed *that, Value *args, int argc) +Value ObjectCtor::construct(Managed *that, const CallData &d) { ObjectCtor *ctor = static_cast(that); ExecutionEngine *v4 = that->engine(); - if (!argc || args[0].isUndefined() || args[0].isNull()) { + if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull()) { Object *obj = v4->newObject(); Value proto = ctor->get(v4->id_prototype); if (proto.isObject()) obj->prototype = proto.objectValue(); return Value::fromObject(obj); } - return __qmljs_to_object(v4->current, args[0]); + return __qmljs_to_object(v4->current, d.args[0]); } -Value ObjectCtor::call(Managed *m, const Value &/*thisObject*/, Value *args, int argc) +Value ObjectCtor::call(Managed *m, const CallData &d) { - if (!argc || args[0].isUndefined() || args[0].isNull()) + if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull()) return Value::fromObject(m->engine()->newObject()); - return __qmljs_to_object(m->engine()->current, args[0]); + return __qmljs_to_object(m->engine()->current, d.args[0]); } void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor) @@ -385,7 +385,9 @@ Value ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx) FunctionObject *f = ts.asFunctionObject(); if (!f) ctx->throwTypeError(); - return f->call(Value::fromObject(o), 0, 0); + CALLDATA(0); + d.thisObject = Value::fromObject(o); + return f->call(d); } Value ObjectPrototype::method_valueOf(SimpleCallContext *ctx) diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h index ca2e77ca42..afa0ce09f5 100644 --- a/src/qml/jsruntime/qv4objectproto_p.h +++ b/src/qml/jsruntime/qv4objectproto_p.h @@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject { ObjectCtor(ExecutionContext *scope); - static Value construct(Managed *that, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *that, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index f79675845b..70413489aa 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -701,18 +701,19 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase QV4::ExecutionEngine *v4 = f->internalClass->engine; QV4::ExecutionContext *ctx = v4->current; - QVarLengthArray args(argCount); + CALLDATA(argCount); + d.thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value(); for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; if (type == qMetaTypeId()) { - args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); + d.args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); } else { - args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1])); + d.args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1])); } } try { - f->call(This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value(), args.data(), argCount); + f->call(d); } catch (QV4::Exception &e) { e.accept(ctx); QQmlError error; @@ -1686,17 +1687,17 @@ QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args return QV4::Value::undefinedValue(); } -Value QObjectMethod::call(Managed *m, const Value &thisObject, Value *args, int argc) +Value QObjectMethod::call(Managed *m, const CallData &d) { QObjectMethod *This = static_cast(m); - return This->callInternal(thisObject, args, argc); + return This->callInternal(d); } -Value QObjectMethod::callInternal(const Value &, Value *args, int argc) +Value QObjectMethod::callInternal(const CallData &d) { ExecutionContext *context = engine()->current; if (m_index == DestroyMethod) - return method_destroy(context, args, argc); + return method_destroy(context, d.args, d.argc); else if (m_index == ToStringMethod) return method_toString(context); @@ -1731,7 +1732,7 @@ Value QObjectMethod::callInternal(const Value &, Value *args, int argc) if (method.isV4Function()) { QV4::Value rv = QV4::Value::undefinedValue(); - QQmlV4Function func(argc, args, &rv, m_qmlGlobal.value(), + QQmlV4Function func(d.argc, d.args, &rv, m_qmlGlobal.value(), QmlContextWrapper::getContext(m_qmlGlobal.value()), v8Engine); QQmlV4Function *funcptr = &func; @@ -1742,7 +1743,7 @@ Value QObjectMethod::callInternal(const Value &, Value *args, int argc) return rv; } - CallArgs callArgs(argc, args); + CallArgs callArgs(d.argc, d.args); if (!method.isOverload()) { return CallPrecise(object, method, v8Engine, callArgs); } else { diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 6580d19fe9..39af02f38b 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -141,9 +141,9 @@ private: int m_index; QV4::PersistentValue m_qmlGlobal; - static Value call(Managed *, const Value &thisObject, Value *args, int argc); + static Value call(Managed *, const CallData &d); - Value callInternal(const Value &, Value *args, int argc); + Value callInternal(const CallData &d); static void destroy(Managed *that) { diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 0dc14e5722..16b23e2edb 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -220,10 +220,10 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value RegExpCtor::construct(Managed *m, Value *argv, int argc) +Value RegExpCtor::construct(Managed *m, const CallData &d) { - Value r = argc > 0 ? argv[0] : Value::undefinedValue(); - Value f = argc > 1 ? argv[1] : Value::undefinedValue(); + Value r = d.argc > 0 ? d.args[0] : Value::undefinedValue(); + Value f = d.argc > 1 ? d.args[1] : Value::undefinedValue(); ExecutionContext *ctx = m->engine()->current; if (RegExpObject *re = r.as()) { if (!f.isUndefined()) @@ -264,14 +264,14 @@ Value RegExpCtor::construct(Managed *m, Value *argv, int argc) return Value::fromObject(o); } -Value RegExpCtor::call(Managed *that, const Value &, Value *argv, int argc) +Value RegExpCtor::call(Managed *that, const CallData &d) { - if (argc > 0 && argv[0].as()) { - if (argc == 1 || argv[1].isUndefined()) - return argv[0]; + if (d.argc > 0 && d.args[0].as()) { + if (d.argc == 1 || d.args[1].isUndefined()) + return d.args[0]; } - return construct(that, argv, argc); + return construct(that, d); } void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor) @@ -349,7 +349,10 @@ Value RegExpPrototype::method_compile(SimpleCallContext *ctx) if (!r) ctx->throwTypeError(); - RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(ctx->arguments, ctx->argumentCount).as(); + CallData d; + d.args = ctx->arguments; + d.argc = ctx->argumentCount; + RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(d).as(); r->value = re->value; r->global = re->global; diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h index 0b9b7122a9..2179dbdb7d 100644 --- a/src/qml/jsruntime/qv4regexpobject_p.h +++ b/src/qml/jsruntime/qv4regexpobject_p.h @@ -98,8 +98,8 @@ struct RegExpCtor: FunctionObject { RegExpCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *m, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 8d28979b60..f145050f17 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -446,14 +446,18 @@ Value __qmljs_object_default_value(Object *object, int typeHint) Value conv = object->get(meth1); if (FunctionObject *o = conv.asFunctionObject()) { - Value r = o->call(Value::fromObject(object), 0, 0); + CALLDATA(0); + d.thisObject = Value::fromObject(object); + Value r = o->call(d); if (r.isPrimitive()) return r; } conv = object->get(meth2); if (FunctionObject *o = conv.asFunctionObject()) { - Value r = o->call(Value::fromObject(object), 0, 0); + CALLDATA(0); + d.thisObject = Value::fromObject(object); + Value r = o->call(d); if (r.isPrimitive()) return r; } @@ -600,9 +604,10 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value return; } - Value args[1]; - args[0] = value; - setter->call(Value::fromObject(o), args, 1); + CALLDATA(1); + d.args[0] = value; + d.thisObject = Value::fromObject(o); + setter->call(d); return; } } @@ -730,7 +735,11 @@ void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint i return; } - Value res = o->call(thisObject, args, argc); + CallData d; + d.thisObject = thisObject; + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -758,7 +767,11 @@ void __qmljs_call_activation_property(ExecutionContext *context, Value *result, return; } - Value res = o->call(thisObject, args, argc); + CallData d; + d.thisObject = thisObject; + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -784,7 +797,11 @@ void __qmljs_call_property(ExecutionContext *context, Value *result, const Value context->throwTypeError(error); } - Value res = o->call(thisObject, args, argc); + CallData d; + d.thisObject = thisObject; + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -807,7 +824,11 @@ void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, cons if (!o) context->throwTypeError(); - Value res = o->call(thisObject, args, argc); + CallData d; + d.thisObject = thisObject; + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -822,7 +843,11 @@ void __qmljs_call_element(ExecutionContext *context, Value *result, const Value if (!o) context->throwTypeError(); - Value res = o->call(thisObject, args, argc); + CallData d; + d.thisObject = thisObject; + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -832,7 +857,11 @@ void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *t Object *o = func.asObject(); if (!o) context->throwTypeError(); - Value res = o->call(thisObject ? *thisObject : Value::undefinedValue(), args, argc); + CallData d; + d.thisObject = thisObject ? *thisObject : Value::undefinedValue(); + d.args = args; + d.argc = argc; + Value res = o->call(d); if (result) *result = res; } @@ -845,7 +874,10 @@ void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, u l->globalGetter(l, context, &func); if (Object *f = func.asObject()) { - Value res = f->construct(args, argc); + CallData d; + d.args = args; + d.argc = argc; + Value res = f->construct(d); if (result) *result = res; return; @@ -864,7 +896,10 @@ void __qmljs_construct_activation_property(ExecutionContext *context, Value *res void __qmljs_construct_value(ExecutionContext *context, Value *result, const Value &func, Value *args, int argc) { if (Object *f = func.asObject()) { - Value res = f->construct(args, argc); + CallData d; + d.args = args; + d.argc = argc; + Value res = f->construct(d); if (result) *result = res; return; @@ -879,7 +914,10 @@ void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value func = thisObject->get(name); if (Object *f = func.asObject()) { - Value res = f->construct(args, argc); + CallData d; + d.args = args; + d.argc = argc; + Value res = f->construct(d); if (result) *result = res; return; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 80cca830f5..17bd9b5eed 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -78,7 +78,7 @@ struct QmlBindingWrapper : FunctionObject scope->engine->popContext(); } - static Value call(Managed *that, const Value &, Value *, int); + static Value call(Managed *that, const CallData &); static void markObjects(Managed *m) { QmlBindingWrapper *wrapper = static_cast(m); @@ -121,7 +121,7 @@ struct CompilationUnitHolder : public QV4::Object DEFINE_MANAGED_VTABLE(CompilationUnitHolder); -Value QmlBindingWrapper::call(Managed *that, const Value &, Value *, int) +Value QmlBindingWrapper::call(Managed *that, const CallData &) { ExecutionEngine *engine = that->engine(); QmlBindingWrapper *This = static_cast(that); @@ -247,7 +247,9 @@ Value Script::run() } else { FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject()); - return f->call(Value::undefinedValue(), 0, 0); + CALLDATA(0); + d.thisObject = Value::undefinedValue(); + return f->call(d); } } diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index c248c9c524..1d5c271069 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -353,11 +353,11 @@ public: bool operator()(typename Container::value_type lhs, typename Container::value_type rhs) { QV4::Managed *fun = this->m_compareFn.asManaged(); - QV4::Value argv[2] = { - convertElementToValue(this->m_ctx->engine, lhs), - convertElementToValue(this->m_ctx->engine, rhs) - }; - QV4::Value result = fun->call(QV4::Value::fromObject(this->m_ctx->engine->globalObject), argv, 2); + CALLDATA(2); + d.args[0] = convertElementToValue(this->m_ctx->engine, lhs); + d.args[1] = convertElementToValue(this->m_ctx->engine, rhs); + d.thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject); + QV4::Value result = fun->call(d); return result.toNumber() < 0; } diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index e0c6bb5a17..ab802cabce 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -148,21 +148,21 @@ StringCtor::StringCtor(ExecutionContext *scope) vtbl = &static_vtbl; } -Value StringCtor::construct(Managed *m, Value *argv, int argc) +Value StringCtor::construct(Managed *m, const CallData &d) { Value value; - if (argc) - value = Value::fromString(argv[0].toString(m->engine()->current)); + if (d.argc) + value = Value::fromString(d.args[0].toString(m->engine()->current)); else value = Value::fromString(m->engine()->current, QString()); return Value::fromObject(m->engine()->newStringObject(value)); } -Value StringCtor::call(Managed *m, const Value &, Value *argv, int argc) +Value StringCtor::call(Managed *m, const CallData &d) { Value value; - if (argc) - value = Value::fromString(argv[0].toString(m->engine()->current)); + if (d.argc) + value = Value::fromString(d.args[0].toString(m->engine()->current)); else value = Value::fromString(m->engine()->current, QString()); return value; @@ -340,8 +340,11 @@ Value StringPrototype::method_match(SimpleCallContext *context) Value regexp = context->argumentCount ? context->arguments[0] : Value::undefinedValue(); RegExpObject *rx = regexp.as(); - if (!rx) - rx = context->engine->regExpCtor.asFunctionObject()->construct(®exp, 1).as(); + if (!rx) { + CALLDATA(1); + d.args[0] = regexp; + rx = context->engine->regExpCtor.asFunctionObject()->construct(d).as(); + } if (!rx) // ### CHECK @@ -352,9 +355,11 @@ Value StringPrototype::method_match(SimpleCallContext *context) // ### use the standard builtin function, not the one that might be redefined in the proto FunctionObject *exec = context->engine->regExpPrototype->get(context->engine->newString(QStringLiteral("exec")), 0).asFunctionObject(); - Value arg = Value::fromString(s); + CALLDATA(1); + d.thisObject = Value::fromObject(rx); + d.args[0] = Value::fromString(s); if (!global) - return exec->call(Value::fromObject(rx), &arg, 1); + return exec->call(d); String *lastIndex = context->engine->newString(QStringLiteral("lastIndex")); rx->put(lastIndex, Value::fromInt32(0)); @@ -363,7 +368,7 @@ Value StringPrototype::method_match(SimpleCallContext *context) double previousLastIndex = 0; uint n = 0; while (1) { - Value result = exec->call(Value::fromObject(rx), &arg, 1); + Value result = exec->call(d); if (result.isNull()) break; assert(result.isObject()); @@ -477,8 +482,8 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx) Value replaceValue = ctx->argument(1); if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) { int replacementDelta = 0; - int argc = numCaptures + 2; - Value *args = (Value*)alloca((numCaptures + 2) * sizeof(Value)); + CALLDATA(numCaptures + 2); + d.thisObject = Value::undefinedValue(); for (int i = 0; i < numStringMatches; ++i) { for (int k = 0; k < numCaptures; ++k) { int idx = (i * numCaptures + k) * 2; @@ -487,13 +492,14 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx) Value entry = Value::undefinedValue(); if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch) entry = Value::fromString(ctx, string.mid(start, end - start)); - args[k] = entry; + d.args[k] = entry; } uint matchStart = matchOffsets[i * numCaptures * 2]; uint matchEnd = matchOffsets[i * numCaptures * 2 + 1]; - args[numCaptures] = Value::fromUInt32(matchStart); - args[numCaptures + 1] = Value::fromString(ctx, string); - Value replacement = searchCallback->call(Value::undefinedValue(), args, argc); + d.args[numCaptures] = Value::fromUInt32(matchStart); + d.args[numCaptures + 1] = Value::fromString(ctx, string); + + Value replacement = searchCallback->call(d); QString replacementString = replacement.toString(ctx)->toQString(); result.replace(replacementDelta + matchStart, matchEnd - matchStart, replacementString); replacementDelta += replacementString.length() - matchEnd + matchStart; @@ -529,7 +535,9 @@ Value StringPrototype::method_search(SimpleCallContext *ctx) Value regExpValue = ctx->argument(0); RegExpObject *regExp = regExpValue.as(); if (!regExp) { - regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(®ExpValue, 1); + CALLDATA(1); + d.args[0] = regExpValue; + regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(d); regExp = regExpValue.as(); } uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint)); diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 0ef6596235..cf489eb05c 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -69,8 +69,8 @@ struct StringCtor: FunctionObject { StringCtor(ExecutionContext *scope); - static Value construct(Managed *m, Value *args, int argc); - static Value call(Managed *that, const Value &, Value *, int); + static Value construct(Managed *m, const CallData &d); + static Value call(Managed *that, const CallData &d); protected: static const ManagedVTable static_vtbl; diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 20b78a4da1..73d5d0479d 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -320,11 +320,11 @@ inline ErrorObject *Value::asErrorObject() const } // ### -inline Value Managed::construct(Value *args, int argc) { - return vtbl->construct(this, args, argc); +inline Value Managed::construct(const CallData &d) { + return vtbl->construct(this, d); } -inline Value Managed::call(const Value &thisObject, Value *args, int argc) { - return vtbl->call(this, thisObject, args, argc); +inline Value Managed::call(const CallData &d) { + return vtbl->call(this, d); } struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 0c922294b4..08344c4c60 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -183,8 +183,11 @@ void QQmlBoundSignalExpression::evaluate(void **a) int *argsTypes = QQmlPropertyCache::methodParameterTypes(m_target, methodIndex, dummy, 0); int argCount = argsTypes ? *argsTypes : 0; - QVarLengthArray args(argCount); - + QV4::Value *args = (QV4::Value *)alloca(qMax(argCount, (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value)); +#ifndef QT_NO_DEBUG + for (int ii = 0; ii < qMax(argCount, (int)QV4::Global::ReservedArgumentCount); ++ii) + args[ii] = QV4::Value::undefinedValue(); +#endif for (int ii = 0; ii < argCount; ++ii) { int type = argsTypes[ii + 1]; //### ideally we would use metaTypeToJS, however it currently gives different results @@ -207,7 +210,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) } } - QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), argCount, args.data(), 0); + QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), argCount, args, 0); } ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 8f1233555b..5c26f689de 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1225,8 +1225,11 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (!valuemap.isEmpty()) { QQmlComponentExtension *e = componentExtension(v8engine); QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject()); - QV4::Value args[] = { object, valuemap }; - f.asFunctionObject()->call(QV4::Value::fromObject(v4engine->globalObject), args, 2); + CALLDATA(2); + d.thisObject = QV4::Value::fromObject(v4engine->globalObject); + d.args[0] = object; + d.args[1] = valuemap; + f.asFunctionObject()->call(d); } d->completeCreate(); @@ -1369,8 +1372,11 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu if (!valuemap.isEmpty()) { QQmlComponentExtension *e = componentExtension(v8engine); QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject()); - QV4::Value args[] = { object, valuemap }; - f.asFunctionObject()->call(QV4::Value::fromObject(v4engine->globalObject), args, 2); + CALLDATA(2); + d.thisObject = QV4::Value::fromObject(v4engine->globalObject); + d.args[0] = object; + d.args[1] = valuemap; + f.asFunctionObject()->call(d); } } @@ -1465,8 +1471,11 @@ void QmlIncubatorObject::setInitialState(QObject *o) QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8); QV4::Value f = QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject()); - QV4::Value args[] = { QV4::QObjectWrapper::wrap(v4, o), valuemap }; - f.asFunctionObject()->call(QV4::Value::fromObject(v4->globalObject), args, 2); + CALLDATA(2); + d.thisObject = QV4::Value::fromObject(v4->globalObject); + d.args[0] = QV4::QObjectWrapper::wrap(v4, o); + d.args[1] = valuemap; + f.asFunctionObject()->call(d); } } @@ -1498,9 +1507,11 @@ void QmlIncubatorObject::statusChanged(Status s) if (QV4::FunctionObject *f = callback.asFunctionObject()) { QV4::ExecutionContext *ctx = f->engine()->current; - QV4::Value args[] = { QV4::Value::fromUInt32(s) }; try { - f->call(QV4::Value::fromObject(this), args, 1); + CALLDATA(1); + d.thisObject = QV4::Value::fromObject(this); + d.args[0] = QV4::Value::fromUInt32(s); + f->call(d); } catch (QV4::Exception &e) { e.accept(ctx); QQmlError error; diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index 3b703c9c2a..41be44a0a7 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -125,7 +125,8 @@ QV4::Value QQmlJavaScriptExpression::evaluate(QQmlContextData *context, const QV4::Value &function, bool *isUndefined) { - return evaluate(context, function, 0, 0, isUndefined); + QV4::Value args[QV4::Global::ReservedArgumentCount]; + return evaluate(context, function, 0, args, isUndefined); } QV4::Value @@ -172,7 +173,11 @@ QQmlJavaScriptExpression::evaluate(QQmlContextData *context, This = value; } - result = function.asFunctionObject()->call(This, args, argc); + QV4::CallData d; + d.thisObject = This; + d.args = args; + d.argc = argc; + result = function.asFunctionObject()->call(d); if (isUndefined) *isUndefined = result.isUndefined(); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 327b638068..3d2d54ccfa 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -926,15 +926,16 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) QQmlVMEMetaData::MethodData *data = metaData->methodData() + id; - QVarLengthArray args(data->parameterCount); + CALLDATA(data->parameterCount); + d.thisObject = ep->v8engine()->global(); for (int ii = 0; ii < data->parameterCount; ++ii) - args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]); + d.args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]); QV4::Value result = QV4::Value::undefinedValue(); QV4::ExecutionContext *ctx = function->engine()->current; try { - result = function->call(ep->v8engine()->global(), args.data(), data->parameterCount); + result = function->call(d); if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0); } catch (QV4::Exception &e) { e.accept(ctx); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index fb6733ee58..5045d700ed 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1482,8 +1482,11 @@ void QQmlXMLHttpRequest::dispatchCallback(const Value &me) v4->current->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject")); QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject); - if (callingContext) - callback->call(activationObject, 0, 0); + if (callingContext) { + CALLDATA(0); + d.thisObject = activationObject; + callback->call(d); + } // if the callingContext object is no longer valid, then it has been // deleted explicitly (e.g., by a Loader deleting the itemContext when @@ -1562,7 +1565,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject if (c->proto) c->proto->mark(); } - static Value construct(Managed *that, Value *, int) + static Value construct(Managed *that, const QV4::CallData &) { QQmlXMLHttpRequestCtor *ctor = that->as(); if (!ctor) @@ -1575,7 +1578,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject return Value::fromObject(w); } - static Value call(Managed *, const Value &, Value *, int) { + static Value call(Managed *, const QV4::CallData &) { return Value::undefinedValue(); } diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index ed972b64c1..ac1cdef30e 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1184,10 +1184,10 @@ struct BindingFunction : public QV4::FunctionObject bindingKeyFlag = true; } - static Value call(Managed *that, const Value &thisObject, Value *argv, int argc) + static Value call(Managed *that, const CallData &d) { BindingFunction *This = static_cast(that); - return This->originalFunction->call(thisObject, argv, argc); + return This->originalFunction->call(d); } static void markObjects(Managed *that) diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 75ed18ce15..96c92c4c7c 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -440,8 +440,10 @@ void QV8Engine::initializeGlobal() void QV8Engine::freezeObject(const QV4::Value &value) { - QV4::Value args = value; - m_freezeObject.value().asFunctionObject()->call(QV4::Value::fromObject(m_v4Engine->globalObject), &args, 1); + CALLDATA(1); + d.args[0] = value; + d.thisObject = QV4::Value::fromObject(m_v4Engine->globalObject); + m_freezeObject.value().asFunctionObject()->call(d); } void QV8Engine::gc() diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 40e33ceef8..91b20e6d81 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -75,20 +75,20 @@ struct DelegateModelGroupFunction: QV4::FunctionObject isBuiltinFunction = true; } - static QV4::Value construct(QV4::Managed *m, QV4::Value *, int) + static QV4::Value construct(QV4::Managed *m, const QV4::CallData &) { m->engine()->current->throwTypeError(); return QV4::Value::undefinedValue(); } - static QV4::Value call(QV4::Managed *that, const QV4::Value &thisObject, QV4::Value *args, int argc) + static QV4::Value call(QV4::Managed *that, const QV4::CallData &d) { DelegateModelGroupFunction *f = static_cast(that); - QQmlDelegateModelItemObject *o = thisObject.as(); + QQmlDelegateModelItemObject *o = d.thisObject.as(); if (!o) that->engine()->current->throwTypeError(QStringLiteral("Not a valid VisualData object")); - QV4::Value v = argc ? args[0] : QV4::Value::undefinedValue(); + QV4::Value v = d.argc ? d.args[0] : QV4::Value::undefinedValue(); return f->code(o->item, f->flag, v); } }; diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 1ec6a45fe0..8822eaecd0 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -233,19 +233,23 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() QV4::Value function = QV4::Value::fromObject(m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, m_v4Engine->newString(QStringLiteral("sendMessage")), QQuickWorkerScriptEnginePrivate::sendMessage)); - QV4::Value args[] = { function }; - createsend = createsendconstructor->call(global(), args, 1); + CALLDATA(1); + d.args[0] = function; + d.thisObject = global(); + createsend = createsendconstructor->call(d); } // Requires handle and context scope QV4::Value QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id) { - QV4::Value args[] = { QV4::Value::fromInt32(id) }; QV4::FunctionObject *f = createsend.value().asFunctionObject(); QV4::Value v = QV4::Value::undefinedValue(); QV4::ExecutionContext *ctx = f->internalClass->engine->current; try { - v = f->call(global(), args, 1); + CALLDATA(1); + d.args[0] = QV4::Value::fromInt32(id); + d.thisObject = global(); + v = f->call(d); } catch (QV4::Exception &e) { e.accept(ctx); v = e.value(); @@ -343,11 +347,15 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d QV4::Value value = QV4::Serialize::deserialize(data, workerEngine); - QV4::Value args[] = { script->object.value(), value }; QV4::FunctionObject *f = workerEngine->onmessage.value().asFunctionObject(); QV4::ExecutionContext *ctx = f->internalClass->engine->current; + try { - workerEngine->onmessage.value().asFunctionObject()->call(workerEngine->global(), args, 2); + CALLDATA(2); + d.thisObject = workerEngine->global(); + d.args[0] = script->object.value(); + d.args[1] = value; + f->call(d); } catch (QV4::Exception &e) { e.accept(ctx); QQmlError error; diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index c1df858310..2538cad211 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -661,10 +661,12 @@ void QQuickCanvasItem::updatePolish() foreach (int key, animationCallbacks.keys()) { QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(qmlEngine(this)); - QV4::Value self = QV4::QObjectWrapper::wrap(v4, this); - QV4::Value args[] = { QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t()) }; QV4::FunctionObject *f = animationCallbacks.value(key).value().asFunctionObject(); - f->call(self, args, 1); + + CALLDATA(1); + d.thisObject = QV4::QObjectWrapper::wrap(v4, this); + d.args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t()); + f->call(d); } } else { -- cgit v1.2.3